NextAuth OAuth Integration#
Langfuse uses NextAuth.js for all authentication, configured in web/src/server/auth.ts. The central export is getAuthOptions(), which assembles static and dynamic SSO providers, a customized Prisma adapter, and NextAuth callbacks.
Sessions use the JWT strategy with a configurable max age .
Supported Providers#
Langfuse ships with the following built-in OAuth/OIDC providers, each activated by setting the corresponding environment variables :
| Provider | Key env vars |
|---|---|
AUTH_GOOGLE_CLIENT_ID, AUTH_GOOGLE_CLIENT_SECRET | |
| GitHub (cloud) | AUTH_GITHUB_CLIENT_ID, AUTH_GITHUB_CLIENT_SECRET |
| GitHub Enterprise | AUTH_GITHUB_ENTERPRISE_CLIENT_ID, AUTH_GITHUB_ENTERPRISE_BASE_URL |
| GitLab | AUTH_GITLAB_CLIENT_ID, AUTH_GITLAB_CLIENT_SECRET |
| Azure AD | AUTH_AZURE_AD_CLIENT_ID, AUTH_AZURE_AD_CLIENT_SECRET, AUTH_AZURE_AD_TENANT_ID |
| Okta | AUTH_OKTA_CLIENT_ID, AUTH_OKTA_CLIENT_SECRET, AUTH_OKTA_ISSUER |
| Auth0 | AUTH_AUTH0_CLIENT_ID, AUTH_AUTH0_CLIENT_SECRET, AUTH_AUTH0_ISSUER |
| Cognito | AUTH_COGNITO_CLIENT_ID, AUTH_COGNITO_CLIENT_SECRET, AUTH_COGNITO_ISSUER |
| Keycloak | AUTH_KEYCLOAK_CLIENT_ID, AUTH_KEYCLOAK_CLIENT_SECRET, AUTH_KEYCLOAK_ISSUER |
| Authentik | AUTH_AUTHENTIK_CLIENT_ID, AUTH_AUTHENTIK_CLIENT_SECRET, AUTH_AUTHENTIK_ISSUER |
| OneLogin | AUTH_ONELOGIN_CLIENT_ID, AUTH_ONELOGIN_CLIENT_SECRET, AUTH_ONELOGIN_ISSUER |
| JumpCloud | AUTH_JUMPCLOUD_CLIENT_ID, AUTH_JUMPCLOUD_CLIENT_SECRET, AUTH_JUMPCLOUD_ISSUER |
| WorkOS | AUTH_WORKOS_CLIENT_ID, AUTH_WORKOS_CLIENT_SECRET |
| WordPress | AUTH_WORDPRESS_CLIENT_ID, AUTH_WORDPRESS_CLIENT_SECRET |
| Custom OIDC | AUTH_CUSTOM_CLIENT_ID, AUTH_CUSTOM_CLIENT_SECRET, AUTH_CUSTOM_ISSUER, AUTH_CUSTOM_NAME |
Enterprise multi-tenant SSO providers are loaded dynamically at runtime via loadSsoProviders() .
Every provider accepts an AUTH_<PROVIDER>_ALLOW_ACCOUNT_LINKING flag (defaults false) that maps to NextAuth's allowDangerousEmailAccountLinking option, enabling linking of a new OAuth identity to an existing account with the same email .
Custom OIDC Provider#
The CustomSSOProvider in packages/shared/src/server/auth/customSsoProvider.ts is a generic OIDC wrapper for any standards-compliant IdP. It supports overriding the JWT claims used to extract user identity via :
LANGFUSE_CUSTOM_SSO_EMAIL_CLAIM— defaults toemailLANGFUSE_CUSTOM_SSO_NAME_CLAIM— defaults tonameLANGFUSE_CUSTOM_SSO_SUB_CLAIM— defaults tosub
This is critical for IdPs like Azure AD that may return email in preferred_username or upn instead of email .
Custom PrismaAdapter Extensions#
Langfuse wraps the standard PrismaAdapter with extendedPrismaAdapter , overriding three methods:
createUser#
Enforces signup guards before delegating to the base adapter :
- Throws if
AUTH_DISABLE_SIGNUP=trueorNEXT_PUBLIC_SIGN_UP_DISABLED=true - Throws if the profile lacks an email address
- After creation, calls
createProjectMembershipsOnSignupto assign default org/project memberships
linkAccount#
Sanitizes provider-specific fields that are incompatible with the Prisma schema before persisting the OAuth account record :
- Keycloak: removes
refresh_expires_inandnot-before-policy— known incompatibilities tracked in nextauthjs/next-auth#7655 - WorkOS: removes the
profilefield - Any provider: fields listed in
AUTH_IGNORE_ACCOUNT_FIELDS(comma-separated) are deleted before the upsert
After linking, createProjectMembershipsOnSignup is called again for the linked user — this handles existing users who log in via SSO for the first time and should receive default memberships .
useVerificationToken#
Adds anti-enumeration protection for email OTP (used in the password-reset flow): on failure or error, all tokens for that identifier are purged and the failure is logged .
Signup Control#
| Variable | Effect |
|---|---|
AUTH_DISABLE_SIGNUP=true | Blocks createUser — prevents all new user provisioning, including OAuth |
NEXT_PUBLIC_SIGN_UP_DISABLED=true | Same effect, checked alongside AUTH_DISABLE_SIGNUP |
AUTH_DISABLE_USERNAME_PASSWORD=true | Disables email/password login only; OAuth signup remains open |
Common pitfall: Setting
AUTH_DISABLE_SIGNUP=trueblocks new users from signing up via SSO too, not just email/password. New SSO users getOAuthCreateAccounterrors. UseAUTH_DISABLE_USERNAME_PASSWORD=trueto force SSO-only logins without blocking auto-provisioning .
signIn Callback#
The signIn callback runs on every authentication attempt:
- Validates that
user.emailis present and well-formed. - Enforces enterprise multi-tenant SSO domain rules (redirects to error page if the user's email domain is locked to a different provider).
- Restricts email-OTP (password reset) sign-in to users who already exist in the database.
- Optionally restricts Google logins to specific hosted domains via
AUTH_GOOGLE_ALLOWED_DOMAINS.
Key Files#
| File | Purpose |
|---|---|
web/src/server/auth.ts | Main NextAuth config: providers, adapter, callbacks |
packages/shared/src/server/auth/customSsoProvider.ts | Generic OIDC provider with configurable claims |
web/src/features/auth/lib/createProjectMembershipsOnSignup.ts | Post-signup membership provisioning |
web/src/env.mjs | Environment variable schema for all auth settings |
web/src/ee/features/multi-tenant-sso/utils | Dynamic SSO provider loading (enterprise) |