OAuth Providers
Sign in with Google, GitHub, and custom OIDC providers (Apple, Microsoft, Auth0, ...)
Looking for how to connect ChatGPT, Claude or an IDE to your Scalix account? That is the opposite direction — Scalix acting as the OAuth provider — and it lives in Connect an app. This page is about signing your end users in with a third-party identity provider.
Supported Providers
| Provider | Status |
|---|---|
| Available | |
| GitHub | Available |
| Any OIDC provider | Available (per-project, see below) |
OAuth Flow
1. Initiate
Request an authorization URL:
curl -X POST https://api.scalix.world/v1/auth/oauth/authorize \
-H "Content-Type: application/json" \
-d '{"provider": "google", "redirect_url": "https://myapp.com/callback"}'Response:
{
"url": "https://accounts.google.com/o/oauth2/v2/auth?...",
"state": "csrf_state"
}Redirect the user to the returned URL.
2. Callback
After the user authorizes, they're redirected to your callback URL with a code:
https://myapp.com/callback?code=auth_code_here&state=csrf_state3. Exchange
Exchange the code for tokens:
curl -X POST https://api.scalix.world/v1/auth/oauth/callback \
-d '{
"provider": "google",
"code": "auth_code_here",
"redirect_url": "https://myapp.com/callback",
"state": "csrf_state"
}'Response:
{
"user": {
"id": "usr_abc123",
"email": "user@gmail.com",
"is_anonymous": false
},
"session": {
"access_token": "eyJhbGciOi...",
"refresh_token": "a1b2c3d4e5...",
"expires_in": 900,
"token_type": "bearer"
}
}Client SDK
The auth SDK handles the OAuth flow:
import { ScalixAuthClient } from "@scalix-world/auth";
const auth = new ScalixAuthClient({ url: "https://api.scalix.world" });
// Returns an authorization URL
const { url } = await auth.signInWithOAuth("google", "https://myapp.com/callback");
window.location.href = url;
// After the IdP redirects back to your callback route:
const { user, session } = await auth.completeOAuthSignIn(
provider, code, "https://myapp.com/callback", state,
);Custom OIDC Providers (Apple, Microsoft, Auth0, ...)
Any OIDC identity provider can be registered per project — no platform release
required. A provider is referenced everywhere as oidc:<slug>.
Register a provider (admin)
curl -X POST https://api.scalix.world/v1/auth/admin/oidc-providers \
-H "Authorization: Bearer $SCALIX_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"slug": "apple",
"display_name": "Apple",
"authorize_url": "https://appleid.apple.com/auth/authorize",
"token_url": "https://appleid.apple.com/auth/token",
"userinfo_url": "https://appleid.apple.com/auth/userinfo",
"client_id": "com.your.app",
"client_secret": "...",
"scopes": ["openid", "email", "name"]
}'List and delete:
curl https://api.scalix.world/v1/auth/admin/oidc-providers \
-H "Authorization: Bearer $SCALIX_SECRET_KEY"
curl -X DELETE https://api.scalix.world/v1/auth/admin/oidc-providers/apple \
-H "Authorization: Bearer $SCALIX_SECRET_KEY"Rules: slug is 1–63 lowercase letters/digits/-/_, unique per project;
all three endpoints must be https (http is accepted only for localhost —
useful for Keycloak/Auth0 in dev); credentials are stored per project and never
returned (client_secret reads back as "configured").
Sign users in
Once the provider row exists, use the normal OAuth endpoints with the composite provider name:
curl -X POST https://api.scalix.world/v1/auth/oauth/authorize \
-d '{"provider": "oidc:apple", "redirect_url": "https://myapp.com/callback"}'const { url } = await auth.signInWithOidc("apple", "https://myapp.com/callback");
window.location.href = url;The flow is the same code + PKCE (S256) exchange as the built-in providers,
against the registered endpoints; the userinfo response is mapped on the
standard sub / email / name / picture claims.
Note: unlike email sign-in, OAuth/OIDC sign-in is not filtered by
allowed_providers (that list gates email, magic-link, and phone methods).
Registering the provider row is what enables it, and deleting the row is what
disables it.
POST for an existing slug returns 409 — delete the provider first if you
need to change its configuration. The userinfo email_verified claim, when the
provider emits it, is enforced; an account that links to an existing local email
keeps the same takeover protections as the Google path.
Account Linking
If a user signs up with email/password and later signs in with Google using the same email, the accounts can be linked via the identity link endpoint:
curl -X POST https://api.scalix.world/v1/auth/identity/link \
-H "Authorization: Bearer $ACCESS_TOKEN"Custom Claims in Tokens
Every access token carries the user's user_metadata and app_metadata
objects (the same objects the profile APIs expose), so your backend can
authorize on roles or plan flags without a second fetch:
{
"sub": "usr_abc123",
"role": "authenticated",
"app_metadata": { "role": "admin", "tier": "pro" },
"user_metadata": { "name": "Alice" }
}role is read from app_metadata.role when set (default authenticated).