Authentication¶
The Centrali SDK supports three authentication methods. Choose the right one based on your use case.
Which method should I use?¶
| Scenario | Method | SDK Option |
|---|---|---|
| Frontend app (React, Vue, public) | Publishable key | publishableKey |
| Frontend with user login (Clerk, Auth0) | External token | getToken |
| Server-side script or backend | Service account | clientId + clientSecret |
Publishable Keys¶
Publishable keys are scoped, browser-safe credentials for frontend apps. They bypass workspace policies — only the key's scopes determine what it can access.
Create a publishable key in Console > ACCESS > Publishable Keys, select which collections, triggers, and files it can access, then use it in your app:
import { CentraliSDK } from '@centrali-io/centrali-sdk';
const centrali = new CentraliSDK({
baseUrl: 'https://centrali.io',
workspaceId: 'my-workspace',
publishableKey: 'pk_live_a1b2c3d4e5f6g7h8',
});
// Read records (if scoped)
const posts = await centrali.queryRecords('posts');
// Submit a form (if scoped)
await centrali.createRecord('contact-submissions', {
name: 'Jane',
message: 'Hello!',
});
Key characteristics:
- Sent as
x-api-keyheader (not Bearer token) - No token refresh needed — the key is static
- Scopes follow
resource:action:targetformat (e.g.,records:list:posts) - Wildcard targets (
*) only allowed for read actions - Admin resources (users, groups, policies) are never accessible
- Rate limited per key: 200 reads/min, 30 writes/min
Security: Publishable keys are safe to expose in client-side code. They are workspace-scoped and can only access the specific resources their scopes allow.
External Tokens (BYOT)¶
If your app has its own authentication (Clerk, Auth0, Okta, etc.), use the getToken callback to pass your provider's JWT to Centrali:
const centrali = new CentraliSDK({
baseUrl: 'https://centrali.io',
workspaceId: 'my-workspace',
getToken: async () => {
// Get a fresh token from your auth provider
return await clerk.session.getToken();
},
});
// Full access governed by ABAC policies
await centrali.updateRecord('posts', 'post-123', { title: 'Updated' });
Key characteristics:
- Token is sent as
Authorization: Bearerheader getTokenis called before each request to ensure a fresh token- On 401, the SDK retries once with a new token from
getToken - Access is governed by ABAC policies (workspace policies, roles, groups apply)
- Requires an external auth provider configured in Console > ACCESS > Auth Providers
You can also pass a static token directly:
const centrali = new CentraliSDK({
baseUrl: 'https://centrali.io',
workspaceId: 'my-workspace',
token: 'eyJhbGciOiJSUzI1NiIs...',
});
Service Accounts¶
Service accounts use OAuth2 client credentials for server-to-server authentication. Never use client secrets in browser code.
const centrali = new CentraliSDK({
baseUrl: 'https://centrali.io',
workspaceId: 'my-workspace',
clientId: process.env.CENTRALI_CLIENT_ID,
clientSecret: process.env.CENTRALI_CLIENT_SECRET,
});
// Full access governed by ABAC policies
await centrali.deleteRecord('posts', 'post-123');
Key characteristics:
- Token is fetched automatically via client credentials grant on first request
- On 401/403, the SDK refreshes the token and retries once
- Access is governed by ABAC policies
- Create service accounts in Console > ACCESS > Service Accounts
Mutual Exclusion¶
Only one auth method can be used at a time. The SDK throws an error if conflicting options are provided:
// This throws: "Cannot use publishableKey with clientId/clientSecret"
new CentraliSDK({
publishableKey: 'pk_live_...',
clientId: 'ci_...',
clientSecret: 'sk_...',
});
Publishable Keys vs ABAC Policies¶
Publishable keys and ABAC policies are separate authorization systems:
| Publishable Keys | ABAC Policies | |
|---|---|---|
| Used by | publishableKey auth path | token, getToken, clientId/clientSecret |
| Authorization | Scopes embedded in the key | Policies evaluated by IAM |
| Managed in | Console > Publishable Keys | Console > Permissions |
| Granularity | resource:action:target | Conditions (time, IP, claims, groups) |
| Admin access | Never | Policy-dependent |
If you need conditional access (time-based, IP-restricted, group-based), use ABAC with user tokens or service accounts. If you need simple, scoped frontend access, use publishable keys.