How Authentication Works¶
Centrali uses OAuth 2.0 for authentication and Resource-Based Access Control (ReBAC) for authorization. All access decisions are workspace-scoped.
Authentication Methods¶
1. Service Account Authentication (API & SDK) [Recommended]¶
Use for: API integrations, SDK usage, server-to-server communication, CI/CD pipelines, production deployments.
- Create a service account in your workspace dashboard
- Receive
client_idandclient_secret - Exchange credentials for a JWT access token
- Use the token in API requests
This is the primary authentication method for building with Centrali.
2. User Authentication (Dashboard Login)¶
Use for: Accessing the Centrali web dashboard and interactive administration.
- Login at centrali.io via email/password or social login (Google, GitHub)
- Session managed automatically via browser cookies
3. External Authentication (BYOT)¶
Use for: Applications that use their own identity provider (Clerk, Auth0, Okta).
Centrali validates your external JWT tokens and maps claims to its authorization system. See External Auth (BYOT) for details.
Service Account Authentication Flow¶
Step 1: Create a Service Account¶
See the Account Setup Guide for detailed instructions.
You'll receive:
Step 2: Obtain an Access Token¶
Exchange your credentials for a JWT token:
Endpoint: POST https://auth.centrali.io/oidc/token
curl -X POST "https://auth.centrali.io/oidc/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=ci_a1b2c3d4e5f6g7h8i9j0" \
-d "client_secret=sk_0123456789abcdef..." \
-d "scope=openid"
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 25200,
"scope": "openid"
}
Token Details: - Lifetime: 7 hours (25,200 seconds) - Type: JWT (JSON Web Token) - Refresh: Request a new token before expiration
Step 3: Use the Token¶
Include the token in the Authorization header:
curl -X GET "https://api.centrali.io/data/workspace/my-workspace/api/v1/structures" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
Using the SDK (Recommended)¶
The Centrali SDK handles token management automatically:
import { CentraliSDK } from '@centrali-io/centrali-sdk';
const centrali = new CentraliSDK({
baseUrl: 'https://api.centrali.io',
workspaceId: 'my-workspace',
clientId: process.env.CENTRALI_CLIENT_ID,
clientSecret: process.env.CENTRALI_CLIENT_SECRET
});
// SDK automatically fetches, caches, and refreshes tokens
const products = await centrali.queryRecords('Product', { limit: 10 });
How Authorization Works¶
Centrali uses a three-tier authorization model:
Resources¶
Resources represent protected entities (e.g., records, structures, files). Each resource defines allowed actions like create, retrieve, update, delete, list.
Policies¶
Policies contain rules that determine access. They use conditions to check attributes like group membership, roles, user identity, IP address, and time of day.
Permissions¶
Permissions connect resources to policies. They specify which actions on a resource are governed by which policy, and at what priority.
For detailed reference on creating custom resources, policies, and permissions, see Policies & Permissions.
Groups and Roles¶
Access is controlled through groups and roles, not fixed permission strings.
Groups¶
Groups are collections of users and/or service accounts. Policies reference groups in their conditions. Default groups include:
workspace_owners— Full accessworkspace_administrators— Broad management access
You can create custom groups for any access pattern (e.g., developers, viewers, api-users).
Roles¶
Roles are named labels assigned to users and service accounts within a workspace. Default roles include:
workspace_owners— Cannot be deleted; identifies workspace owners
How Permissions Flow¶
User / Service Account
↓
Assigned to Groups & Roles
↓
Policies check group/role membership
↓
Permissions link policies to resources + actions
↓
Access Allowed or Denied
Example: To give a group read-only access to records:
- Create a group (e.g.,
readonly-users) - Create a policy that allows access when the user is in
readonly-users - Create a permission linking the
recordsresource to that policy forretrieveandlistactions - Add users to the
readonly-usersgroup
Service Account Access¶
Service accounts get their permissions through group membership, exactly like users.
- Create a service account in the dashboard or via API
- Create or select a group with the appropriate policies
- Add the service account to the group
- The service account inherits all permissions granted to that group
Full Admin Access
To give a service account full workspace access, add it to the workspace_administrators group.
Security Best Practices¶
Storing Credentials¶
- Use environment variables or secret management services
- Never hardcode in source code or commit to version control
- Use different credentials per environment
Credential Rotation¶
- Development: Rotate every 90 days
- Production: Rotate every 30-90 days
- Immediately if credentials are compromised
Token Management¶
- Cache tokens until near expiration (refresh 5 minutes early)
- Use the SDK for automatic token lifecycle management
- Handle 401 errors with re-authentication
Common Authentication Patterns¶
Backend API Service¶
import { CentraliSDK } from '@centrali-io/centrali-sdk';
const centrali = new CentraliSDK({
baseUrl: 'https://api.centrali.io',
workspaceId: process.env.CENTRALI_WORKSPACE,
clientId: process.env.CENTRALI_CLIENT_ID,
clientSecret: process.env.CENTRALI_CLIENT_SECRET
});
app.get('/api/products', async (req, res) => {
const products = await centrali.queryRecords('Product', {
filter: { inStock: true },
limit: 20
});
res.json(products);
});
Serverless Function (Vercel, AWS Lambda)¶
// api/products.js
import { CentraliSDK } from '@centrali-io/centrali-sdk';
// Initialize outside handler for connection reuse
const centrali = new CentraliSDK({
baseUrl: 'https://api.centrali.io',
workspaceId: process.env.CENTRALI_WORKSPACE,
clientId: process.env.CENTRALI_CLIENT_ID,
clientSecret: process.env.CENTRALI_CLIENT_SECRET
});
export default async function handler(req, res) {
const products = await centrali.queryRecords('Product', { limit: 10 });
res.json(products);
}
JWT Token Claims¶
Service account tokens include these claims:
{
"sub": "ci_a1b2c3d4e5f6g7h8i9j0",
"iss": "https://auth.centrali.io",
"aud": "https://api.centrali.io",
"iat": 1705326000,
"exp": 1705351200,
"workspace": "my-workspace",
"isServiceAccount": "true",
"groups": ["developers"],
"roles": ["workspace_owners"]
}
Troubleshooting¶
"Invalid client credentials"¶
- Verify credentials in dashboard
- Check for whitespace in environment variables
- Ensure you're using the correct workspace's credentials
"Token expired"¶
- Tokens expire after 7 hours — fetch a new one
- Use the SDK for automatic token refresh
- Check system clock synchronization
"Forbidden" or "Unauthorized"¶
- Verify workspace slug matches token
- Check
Authorization: Bearer {token}header format - Ensure the service account's group has the required permissions
See the Troubleshooting Guide for more help.
Related Documentation¶
- Account Setup — Create service accounts
- Service Accounts API — Complete API reference
- External Auth (BYOT) — Use your own identity provider
- Policies & Permissions — Custom access rules
- Clerk Integration — Step-by-step Clerk setup
- SDK Guide — Official SDK documentation