concepts
Single Sign-On (SSO)
Multi-provider OIDC-based SSO integration with auto-provisioning, domain mappings, and claim-based role assignments.
Overview
BurnerByte supports multiple SSO providers simultaneously. Providers are stored in the database and managed through the Admin API. A file-based fallback is available for single-provider setups.
Each provider is an OIDC (or OAuth2) integration that lets users authenticate with an external identity provider instead of a password.
Supported Provider Types
| Type | Key | Notes |
|---|---|---|
google | Uses https://accounts.google.com as issuer | |
| GitHub | github | OAuth2-based (not OIDC discovery) |
| Azure AD | azure | Requires tenant_id; issuer is https://login.microsoftonline.com/{tenant}/v2.0 |
| Okta | okta | Requires issuer_url (e.g. https://your-org.okta.com) |
| Generic OIDC | oidc | Any OIDC-compliant provider; requires issuer_url |
Configuration
Database Providers (Recommended)
Providers are created and managed via the Admin SSO API. Each provider record includes client credentials, issuer URL, auto-provisioning settings, allowed domains, and claim mappings. Client secrets are encrypted at rest using the configured encryption.key.
File-Based Fallback
A single provider can be configured in config.yaml for simple deployments:
sso: provider: google client_id: your-client-id client_secret: your-client-secret redirect_url: http://localhost:8080/api/v1/auth/sso/google/callback tenant_id: your-tenant-id issuer_url: https://accounts.google.com auto_provision: true default_org_role: member default_team_role: member allowed_domains: example.com,corp.example.comDatabase providers are loaded first and take precedence: the file-based provider is merged in only if no database provider shares its name, and only when provider, client_id and client_secret are all set.
Authentication Flow
- User clicks "Sign in with SSO" on the login page
- Frontend redirects to
GET /api/v1/auth/sso/{provider} - Server generates a state cookie (600s TTL) and redirects to the OIDC provider with
prompt=select_accountto force the account picker on every login - User authenticates with the provider
- Provider redirects back to
GET /api/v1/auth/sso/{provider}/callback - Server validates the state, exchanges the code for tokens, and extracts user info
- If the user exists, they're logged in. If not and auto-provisioning is enabled, a new account is created
- Server redirects to the frontend login page with a one-time
sso_code(60s TTL), which the frontend exchanges for tokens viaPOST /api/v1/auth/sso/exchange— the web UI requests the refresh token as an httpOnly cookie
The same flow supports account linking — authenticated users can link additional SSO identities by initiating the flow with ?intent=link. Linked identities are listed at GET /api/v1/auth/me/sso and can be removed with DELETE /api/v1/auth/me/sso/{provider}.
Auto-Provisioning
New users are created on first SSO login whenever public registration is allowed. The auto_provision flag controls what happens next — whether the new user is automatically given an org membership (and optionally a team membership). With auto_provision off, the account is created but has no org, and the user is sent to the onboarding flow. The provider configuration controls the defaults:
| Field | Description |
|---|---|
default_org_role | Org role assigned to new users (e.g. member, admin) |
default_team_role | Team role when assigned to a default team |
default_team_id | Team to add the user to on first login (optional) |
Domain mappings are consulted only when public registration is disabled (invite-only mode) and only for users who do not yet exist. In that case a matching mapping lets the user in without an invite and provisions them into every mapped team; archived teams are skipped. They do not replace the provider's default_org_role / default_team_id, which are still applied afterwards when auto_provision is on. Mappings are never re-evaluated for existing users.
Domain Mappings
Domain mappings route users from specific email domains to teams automatically during SSO login. Multiple mappings can exist for the same domain and provider, enabling one domain rule to assign users to multiple teams simultaneously.
Fields
| Field | Description |
|---|---|
domain | Email domain to match (e.g. example.com) |
org_role | Org role to assign (defaults to member) |
team_id | Team to add the user to |
team_role | Role within the team (defaults to member) |
Preview / Dry-Run
Before creating mappings, you can preview what would happen for a given email:
POST /api/v1/admin/sso/domain-mappings/preview{ "email": "alice@example.com", "provider": "google"}Returns the matching rules, predicted org role, and team assignments without making any changes.
Claim Mappings
Claim mappings let you map IdP claims to BurnerByte role and team assignments. Each mapping specifies a claim name, expected value, and the resulting org role and/or team assignment:
{ "claim_name": "groups", "claim_value": "engineering", "org_role": "member", "team_id": "uuid-of-team", "team_role": "lead"}Claim mappings are configured per provider via the claim_mappings field. The custom_claims field on the provider specifies which additional claims to request from the IdP. Claim mappings are applied on a user's first SSO login only, and only when auto_provision is enabled. org_role and team_role must name roles that exist in the roles table (GET /api/v1/roles lists them); values are not validated at write time, so an unknown role silently fails and is only logged. A team assignment requires both team_id and team_role — omitting team_role skips the assignment rather than defaulting to member.
Allowed Domains
Each provider can restrict which email domains are permitted to authenticate. Set the allowed_domains field to a comma-separated list of domains (e.g. example.com,corp.example.com). Users with email addresses outside the allowed domains are rejected during SSO login.
Enforcing SSO
Org admins can enforce SSO for all members via org settings:
PUT /api/v1/orgs/{orgId}/settings{"enforce_sso": true}When enforced, password-based login is disabled for org members. The enforce_sso flag is also surfaced in the SSO status endpoint.
Auth Method Lock and Migration
Auth Method Lock
Each user has an optional auth_method_lock field that restricts which authentication method they can use:
| Value | Effect |
|---|---|
null | Any method allowed (default) |
"sso" | Only SSO login permitted |
"password" | Only password login permitted |
Platform admins can set the lock via PATCH /api/v1/admin/users/:id with the auth_method_lock field.
Auth Migration
Platform admins can migrate users between authentication methods:
POST /api/v1/admin/users/{userId}/migrate-auth{"target": "sso"}POST /api/v1/admin/users/{userId}/migrate-auth{"target": "password", "new_password": "securePassword123"}Migrating to SSO requires the user to already have at least one linked SSO identity — otherwise the call fails with 400. It clears the password hash, sets the auth method lock to sso, and revokes all of the user's sessions. Migrating to password requires a new_password satisfying the active password policy and sets the lock to password; existing sessions are left intact.
SSO Status
Check whether SSO is configured and available:
GET /api/v1/auth/sso-statusReturns the current SSO status including:
enabled— whether any SSO provider is configuredproviders— list of configured providers (name, type, label, enabled status)enforce_sso— whether the org enforces SSO-only loginallow_registration— whether self-registration is enabledpassword_policy— current password policy settings
No secrets are exposed.
Connection Testing
Platform admins can test an SSO provider's connectivity before saving:
POST /api/v1/admin/sso/test{ "name": "google", "provider_type": "google", "client_id": "your-client-id", "client_secret": "your-client-secret"}Returns success/failure, the discovered endpoint, HTTP status code, response time, and a diagnostic message.
Admin API Endpoints
SSO Providers
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/admin/sso/providers | List all SSO providers |
POST | /api/v1/admin/sso/providers | Create a new provider |
GET | /api/v1/admin/sso/providers/:pid | Get a single provider |
PUT | /api/v1/admin/sso/providers/:pid | Update a provider |
DELETE | /api/v1/admin/sso/providers/:pid | Delete a provider |
POST | /api/v1/admin/sso/test | Test provider connectivity |
Domain Mappings
| Method | Endpoint | Description |
|---|---|---|
POST | /api/v1/admin/sso/providers/:pid/domain-mappings | Create a domain mapping |
GET | /api/v1/admin/sso/providers/:pid/domain-mappings | List mappings for a provider |
PUT | /api/v1/admin/sso/providers/:pid/domain-mappings/:mid | Update a domain mapping |
DELETE | /api/v1/admin/sso/providers/:pid/domain-mappings/:mid | Delete a domain mapping |
POST | /api/v1/admin/sso/domain-mappings/preview | Preview mapping results (dry-run) |
Auth Migration
| Method | Endpoint | Description |
|---|---|---|
POST | /api/v1/admin/users/:id/migrate-auth | Migrate user auth method (target: sso or password) |
All admin endpoints require the SystemAdmin role.