Authentication
Password and Clerk are available on every plan. Generic OIDC and SAML 2.0 require the Enterprise plan.
Provider options
Behavry ships with four authentication providers that sit behind a common AuthProvider abstraction. You pick one per tenant and the rest of the product is provider-agnostic.
| Provider | When to use |
|---|---|
| Clerk | SaaS default. Zero-setup. Google / Microsoft / email SSO included. |
| OIDC (generic) | Enterprise IdP integration: Entra ID, Okta, Ping, Auth0, Keycloak, anything OIDC-compliant |
| SAML 2.0 | Enterprise IdPs that only speak SAML (ADFS, older Okta configurations) |
| Password | Local dev, air-gapped deployments, emergency break-glass |
Provider selection lives in TenantConfig.auth_provider; setup is in Settings → Auth. Changing providers requires admin + super-admin approval for safety.
Clerk (default)
Behavry's SaaS and most Hybrid deployments use Clerk by default. Clerk handles sign-up, sign-in, password reset, MFA, social connections, and session management. Behavry consumes Clerk JWTs via JWKS and maps Clerk orgs to Behavry tenants.
What Behavry needs
- Clerk publishable key —
VITE_CLERK_PUBLISHABLE_KEYon the dashboard - Clerk secret key —
BEHAVRY_CLERK_SECRET_KEYon the backend (for org provisioning) - JWT template — Behavry ships a recommended Clerk JWT template that includes
o.id,o.slug, ando.rolclaims
The commercial dashboard, demo.behavry.ai, and docs.behavry.ai each run against separate Clerk instances. This page covers the commercial dashboard's Clerk configuration only. The docs site's sign-in flow is described under Accounts & Sign-In and is intentionally not tenant-aware.
How tenant mapping works
Each Clerk Organization (o.id) maps 1:1 to a Behavry tenant. When a user signs in for the first time with a new org, the backend auto-provisions a matching tenant (backend/behavry/admin/clerk_provider.py). The org role (o.rol) maps to the Behavry role: org:admin → admin, org:policy_author → policy_author, etc.
Token sync
The dashboard runs a ClerkTokenSync component that refreshes the Clerk JWT every 50 seconds (Clerk tokens expire at 60) and writes it to localStorage['behavry_admin_token']. The API client reads from the same key, so the rest of the frontend is Clerk-unaware.
Generic OIDC
For tenants that have an existing corporate IdP.
Configuration
Settings → Auth → OIDC. You provide:
- Issuer URL — e.g.
https://login.microsoftonline.com/{tenant}/v2.0 - Client ID and client secret (client credentials or authorization code flow)
- Scopes — default
openid profile email, add group scopes if your IdP exposes them - Redirect URI — Behavry exposes
/api/v1/auth/sso/oidc/callback - Attribute mapping — how IdP claims map to Behavry user fields:
email(required)namegroups→ Behavry role (rule-based: ifgroupscontainsbehavry_admin→ roleadmin, elseviewer)
Flow
- User hits the dashboard, clicks "Sign in with SSO"
- Dashboard redirects to
/api/v1/auth/sso/oidc/start - Backend redirects to the IdP's authorize endpoint with PKCE
- User authenticates at IdP, returns with a code
- Backend exchanges code for tokens, validates
id_token, maps claims, issues a Behavry session JWT - Dashboard receives the session and the user lands on the home page
All of this lives in backend/behavry/admin/oidc_provider.py and sso_routes.py.
SAML 2.0
SAML is structurally similar to OIDC but uses XML assertions instead of JWTs.
Configuration
Settings → Auth → SAML.
- IdP metadata URL (preferred) or uploaded metadata XML
- Attribute mapping — same idea as OIDC: email, name, groups → role
- ACS URL — Behavry exposes
/api/v1/auth/sso/saml/acs - SLO URL — single logout support, optional
Flow
Standard SP-initiated SAML:
- User clicks "Sign in with SSO"
- Behavry builds an AuthnRequest, redirects to IdP
- IdP authenticates, posts a SAML Response to the ACS URL
- Behavry validates the signature against the IdP's certificate, extracts attributes, issues a session
Source: backend/behavry/admin/saml_routes.py.
Password
For local development, air-gapped deployments, and emergency access.
- Usernames and bcrypt hashes in
admin_users BEHAVRY_ADMIN_USERNAMEandBEHAVRY_ADMIN_PASSWORDenv vars bootstrap the first admin on startupPOST /api/v1/admin/loginreturns a session JWT
Password auth is always reachable at /api/v1/admin/login even when a tenant uses Clerk / OIDC / SAML — this is intentional as a break-glass path. Disable it by deleting every password-enabled admin user.
Role mapping
Regardless of provider, incoming user identities land in the same four roles (see User Roles):
| Role | Hierarchy |
|---|---|
viewer | 1 |
analyst | 2 |
policy_author | 3 |
admin | 4 |
Mapping happens at sign-in. Subsequent API calls carry the role in the session JWT.
Related
- User Roles & Invites
- Settings Hub
- Licensing & Feature Entitlements —
saml_ssois Enterprise-gated