Skip to main content
Prisme.ai provides robust support for enterprise authentication requirements, allowing you to integrate with your existing identity providers through industry-standard protocols. This guide covers the configuration options for Single Sign-On (SSO) integration using OIDC and SAML.

Platform SSO vs Organization SSO

Prisme.ai exposes two levels of SSO configuration, with the same OIDC / SAML config format in both cases; only the place where you declare it changes: Use platform SSO when you operate a single identity provider for all users of the platform. Use organization SSO when each organization brings its own identity provider and you want users to be onboarded into their org automatically. Both can coexist: platform SSO acts as the default, organization SSO overrides for users matching an org’s email pattern. The rest of this page covers the platform level. The config format (provider blocks, attributesMapping, etc.) shown below applies identically to organization SSO; you’ll just paste it into the Governance UI instead of mounting a ConfigMap.

Authentication Overview

Integrating your identity provider with Prisme.ai offers several benefits:

Centralized Identity Management

Manage access through your existing identity provider

Enhanced Security

Enforce your organization’s security policies and MFA requirements

Simplified User Experience

Provide one-click access without separate credentials

Automated Provisioning

Streamline user onboarding and offboarding

Supported Authentication Methods

Prisme.ai supports the following authentication protocols:
OpenID Connect is a modern authentication protocol built on top of OAuth 2.0.Compatible with:
  • Google Workspace
  • Okta
  • Auth0
  • Keycloak
  • Any standards-compliant OIDC provider

Configuring OIDC Authentication

1

Register an Application

Create an OAuth 2.0 client in your OIDC provider.Key configuration:
  1. Register a Web OAuth2 client/app
  2. Configure the authorized redirect URI:
  3. Request the following scopes (minimum):
  4. Add profile scope if you need first name and last name
Note the following credentials:
  • Client ID
  • Client Secret
  • Auth URL (authorization_endpoint)
  • Token URL (token_endpoint)
  • Certificate URL (jwks_uri)
The JWKS URI might not be shown with client details as it is generally global to the IdP or tenant. This URL can return either a standard JWKS or an object mapping kids to PEM certificate strings.Currently, only the RS256 algorithm is supported.
2

Create Configuration File

Create an authProviders.config.yml file with your OIDC provider details.
Choose your <ProviderName> carefully, as this name will be used in front-end services and injected into user authData, making it potentially difficult to change later.
  • The scopes field is optional and defaults to openid email
  • The minimum required scopes are openid and email
  • Add profile scope to retrieve additional user attributes like name
  • attributesMapping maps IdP claim names to Prisme.ai user fields. The defaults above follow the OIDC standard claims (given_name, family_name); set them explicitly if your IdP uses different names

Reading profile claims from the userinfo endpoint

Prisme.ai reads user attributes from the id_token. Some identity providers keep the id_token minimal (only sub) and expose profile claims such as the first and last name on their OIDC /userinfo endpoint instead. Set userinfo_endpoint on the provider to cover that case. When present, Prisme.ai calls it with the access token right after the code exchange and uses its claims to fill the gaps left by the id_token:
What you need from your identity provider:
  • The /userinfo URL. Most providers publish it as userinfo_endpoint in their .well-known/openid-configuration document.
  • Scopes covering the attributes you want back: openid email profile at minimum.
  • An access token in the token endpoint response. Standard OIDC providers always return one; if yours is set up to issue an id_token only, Prisme.ai has nothing to authenticate the /userinfo call with and skips it, logging Skipping the configured userinfo_endpoint: the token endpoint returned no access_token in the api-gateway.
userinfo_endpoint must be an https:// URL, otherwise the provider configuration is rejected. Loopback hosts (localhost, 127.0.0.1, [::1]) are accepted, for pointing at a local IdP during development.
id_token claims always take precedence: only it is signature-verified, so sub, iss, aud and exp can never be overridden by the /userinfo response. A response whose sub does not match the id_token is discarded (OIDC Core 5.3.2).If the endpoint is unreachable, times out or errors, the login still succeeds using the id_token claims alone: the user is simply created without the missing attributes. The call timeout defaults to 5s (OIDC_USERINFO_TIMEOUT, in milliseconds).
Leave userinfo_endpoint unset when your IdP already puts the profile claims in the id_token: it adds one HTTP round-trip to every login for nothing.
You do not need to recreate existing users. Accounts provisioned before you set userinfo_endpoint keep their identity: Prisme.ai refreshes first name, last name and email from the identity provider on every sign-in, so the missing attributes fill in by themselves the next time each user logs in.

Token Exchange (headless clients)

By default an OIDC provider is used through the browser redirect flow (/v2/login → IdP → /v2/login/callback). For clients that have already authenticated against the IdP and hold an id_token (native and mobile apps, desktop clients, CLIs, server-to-server integrations), Prisme.ai can exchange that id_token directly for a nominative JWT, with no browser, via POST /v2/login/token-exchange (see API Authentication). This is disabled by default and must be enabled per provider:
The exchanged id_token is verified against the provider’s jwks_uri, and its aud claim must match client_id. Always set issuer so the iss claim is enforced too; without it, any token signed by the provider’s keys and addressed to your client_id is accepted. Identity mapping (find-or-create user) is identical to the browser callback.
If the provider is declared in authProviders.config.yml, set allowTokenExchange there and restart the api-gateway. If it is managed at the organization level via the API, an org Owner or Admin can update its config without a restart.
The endpoint is rate-limited per source IP via its own counter (RATE_LIMIT_TOKEN_EXCHANGE, default 60/min), independent from anonymous logins. Because token exchange is usually brokered server-side, every end-user shares the same source IP; raise this limit for production deployments serving many users. See Environment Variables.

Configuring SAML Authentication

1

Register Service Provider

Register Prisme.ai as a Service Provider (SP) in your Identity Provider.Key configuration:
  1. Configure the ACS Endpoint:
  2. Set the SP Entity ID: it must be identical to the issuer configured below (see Choosing the SP Entity ID)
  3. Set Name ID format to unspecified (all formats are supported)
Export the IdP metadata XML file containing the signing certificate and entity information.
2

Create Configuration File

Create an authProviders.config.yml file with your SAML provider details.
Choose your <ProviderName> carefully, as this name will be used in front-end services and injected into user authData, making it potentially difficult to change later.
If no XML file is available, you can configure individual parameters:
See node-saml documentation for complete configuration options.

Choosing the SP Entity ID

The SAML 2.0 standard defines the Entity ID as a URI (at most 1024 characters) that must be unique within an identity provider. Any URI works, but the widely followed convention is an https URL on a domain you control. It is only an identifier and does not need to resolve. We recommend one Entity ID per provider, built from your API URL and the provider name:
For example https://api.example.com/saml/customer1 and https://api.example.com/saml/customer2.
Each provider, whether declared in authProviders.config.yml or at the organization level, has its own issuer. Distinct Entity IDs avoid collisions when several configurations go through the same IdP (shared tenant, federation, integrator managing several customers), keep each assertion bound to a single configuration, and make IdP logs easier to read.
Some identity providers and federations reject Entity IDs that are not URIs. Avoid bare strings such as prismeai. Changing the Entity ID later requires updating the IdP side at the same time, or logins fail with an audience mismatch.

Service provider metadata

Each enabled SAML provider publishes Prisme.ai’s service provider metadata (Entity ID, ACS endpoint and, when request signing is on, the signing certificate) at:
Give this URL, or the XML it returns, to your IdP administrator instead of entering each value by hand. The endpoint is public: it only contains what the IdP needs to know about Prisme.ai, and tells whether a SAML provider slug exists. It is rate-limited per source IP (RATE_LIMIT_SAML_METADATA, default 30/min).

Request binding

The binding is how the browser carries the authentication request (AuthnRequest) to the IdP. It is set with authnRequestBinding (the full URN, such as urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect, is also accepted):
When the configuration includes the IdP metadata, the IdP SSO URL (entryPoint) is the SingleSignOnService declared for the chosen binding. An entryPoint set explicitly takes precedence. Switch to HTTP-Redirect when the IdP only accepts it, or when something between the browser and the IdP (reverse proxy, WAF, load balancer) answers the POST with a redirect: the browser then follows it with a GET without body and the request is lost. A typical symptom is the IdP answering 400 with a message such as “Request contains insufficient information to determine the protocol binding”, while the browser shows a GET to the IdP SSO URL without SAMLRequest. HTTP-Redirect requires the request to be compressed (DEFLATE), so skipRequestCompression only applies to HTTP-POST: redirected requests are always compressed, whatever its value. With HTTP-POST, set skipRequestCompression: true if your IdP rejects compressed requests (the SAML standard sends them uncompressed with this binding). With signing enabled, HTTP-POST requests embed an XML signature, while HTTP-Redirect requests carry it in the URL (SigAlg and Signature parameters). The same key and signatureAlgorithm are used. At startup, the api-gateway logs for each SAML provider the IdP SSO URL, the binding, and whether requests are compressed and signed. From the organization SSO page, the binding is the Request Binding field of the SAML provider (see Request binding).

Signing authentication requests

Some identity providers require the authentication requests (AuthnRequests) sent by Prisme.ai to be signed: their metadata then contains WantAuthnRequestsSigned="true". Prisme.ai signs them with an RSA key, and the IdP checks the signature with the matching certificate. This is independent of WantAssertionsSigned, which concerns the assertions the IdP sends back, signed with the IdP’s own certificate (idpCert, or the one read from its metadata).
In AI Governance → Authentication, enable Sign Authentication Requests on the SAML provider and save. A key pair and a self-signed certificate are generated and stored in the provider configuration. Then register the certificate on your IdP, or send it the service provider metadata, which includes it. See Signing authentication requests.
The private key is part of the SSO configuration, encrypted at rest only when SECRETS_MASTER_KEYS is configured (see Secrets Encryption).
Signing is opt-in: signAuthnRequests: true is required. Previous versions passed the whole provider configuration to node-saml, which signed as soon as a privateKey was set. A configuration file that relied on this now sends unsigned requests: add signAuthnRequests: true (and publicCert) to keep signing. The api-gateway logs a warning at startup for any SAML provider that has a privateKey without signAuthnRequests: true.

Mount Configuration File

Whether you configured an OIDC or SAML provider, you can now mount the configuration file inside the prismeai-api-gateway container at /www/services/api-gateway/authProviders.config.yml.
You can customize the file location with the AUTH_PROVIDERS_CONFIG environment variable.
For Kubernetes, store the configuration file in a configmap :
Starting from v27.2.8, the providers config file supports environment variable interpolation through the ${SOME_ENV_VAR} syntax. Any ${VAR} placeholder is resolved against the prismeai-api-gateway container environment at startup.This is typically used to keep sensitive values (e.g. OIDC client_id / client_secret) out of the ConfigMap and inject them from Kubernetes secrets, including secrets synced from an external key vault (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault, …), while leaving the rest of the YAML static:
Then expose the corresponding env vars on the prismeai-api-gateway deployment (e.g. via envFrom / secretKeyRef pointing at your key vault-backed secrets).
Add the following volume and volumeMount to prismeai-api-gateway deployment :

Enable the Provider in UI

Sign-in buttons are rendered automatically by the frontend based on the SSO providers configured at the infrastructure level and in AI Governance. There is nothing to configure on the UI side : any provider declared in your config file will appear on the sign-in page using the label and icon defined there.

Disable local sign-in and sign-up

You can restrict local authentication using the following environment variables on prismeai-api-gateway :
  • DISABLE_LOCAL_SIGNIN disables the local username/password sign-in API. Only SSO providers remain available to log in.
  • DISABLE_LOCAL_SIGNUP disables the local sign-up API. Existing local users can still sign in (unless DISABLE_LOCAL_SIGNIN is also set), but no new local account can be created.

Multi-Factor Authentication (MFA)

Prisme.ai protects local (password) accounts with a second factor. Two methods are available:
  • Passkeys (WebAuthn), the recommended method: the user confirms the sign-in with Face ID, a fingerprint, Windows Hello, their device PIN or a security key. A passkey is bound to your domain, so it cannot be relayed to a phishing site. Passkeys are enabled by default (see Configure passkeys).
  • Authenticator app (TOTP, RFC 6238): the user scans a QR code with Google Authenticator, Microsoft Authenticator, Authy, 1Password or a similar app, then enters a 6-digit code.
MFA applies only to local accounts. SSO accounts are exempt; their identity provider already enforces its own second factor. Anonymous sessions are also exempt.

Require a second factor

Whether local accounts must use a second factor is controlled by one environment variable on prismeai-api-gateway:
  • true (default): every local account must complete a second factor at sign-in.
  • false: the second factor is optional. Users who set one up from their settings are still asked for it.
Existing local users are migrated lazily. When you enable MFA_FORCE_LOCAL, current users are not locked out and no database migration is required; each user sets up a second factor on their next sign-in.

Configure passkeys

Passkeys are enabled by default: you have nothing to configure for a console served over https on a single domain. Every passkey is bound to a domain, called the RP ID. By default it is the domain of your console: for a console served at https://studio.prisme.example.com, the RP ID is studio.prisme.example.com. At startup, prismeai-api-gateway logs the RP ID it uses and where it comes from. To verify, call GET /v2/login/providers on your API: the response contains webauthn.enabled: true, your rpId and the accepted origins. Passkeys only work on the origins you accept, and every origin must be the RP ID itself or one of its subdomains. Workspace pages (*.pages hosts) are deliberately excluded: they run content written by workspace builders, so a passkey used there could be relayed.

Several consoles, or no https

When the default RP ID cannot serve every accepted origin, the gateway turns passkeys off and logs a warning, but still starts. This happens when:
  • your console is served on several domains (for example studio.prisme.example.com and admin.prisme.example.com): set WEBAUTHN_RP_ID to their common parent domain, here prisme.example.com;
  • your console is not served over https: browsers only allow passkeys on https origins and on localhost.
When you set WEBAUTHN_RP_ID yourself, the gateway checks it at startup and refuses to start if an accepted origin cannot use it.

Pin the passkey domain

The RP ID is permanent. Changing it makes every existing passkey unusable. With the default RP ID, changing CONSOLE_URL (or the first entry of WEBAUTHN_ORIGINS) changes it too.
To keep passkeys valid whatever happens to CONSOLE_URL, set WEBAUTHN_RP_ID explicitly, ideally when you first deploy. Use the value the gateway logged at startup if passkeys are already in use, since a different value invalidates them. A passkey can only follow the console within its RP ID. If you expect the console address to change, choose the parent domain from the start: Widening the RP ID later, from studio.prisme.example.com to prisme.example.com, is also a change: it invalidates the existing passkeys.

Move the console to another domain

When the console moves outside its RP ID, passkeys cannot follow. Users can no longer sign in with them, and an account whose only second factor is a passkey stays blocked at the second step. Before the move:
  1. Ask your users to add an authenticator app in Settings > Security > Sign-in methods.
  2. After the move, reset the MFA of the accounts that only had passkeys. They choose a new second factor at their next sign-in.
  3. Set WEBAUTHN_RP_ID to the new domain, or leave the default.

Turn passkeys off

Set WEBAUTHN_ENABLED to false. Passkeys stay stored. An account that only holds passkeys then has no usable second factor: at its next sign-in, it can set up an authenticator app with its password alone. If you do not want that, reset the MFA of those accounts instead, so that they choose a new factor under your control.

User experience

The second factor is requested after a valid password sign-in, before the app loads.
  1. First sign-in: a user without a second factor chooses Create a passkey (recommended) or Use an authenticator app. The passkey option only appears when passkeys are enabled and the browser supports them.
  2. Next sign-ins: the user confirms with their passkey, or enters the 6-digit code of their authenticator app. They can switch to the other method if it is set up.
  3. Passwordless sign-in: with passkeys enabled, the sign-in page offers Sign in with a passkey, and the browser suggests the saved passkeys under the email field. A passkey verified with Face ID, a fingerprint or the device PIN signs the user in without a password and without a second step.
A user can only set up a factor during sign-in if they have none yet. To add, rename or remove factors afterwards, they go to Settings > Security > Sign-in methods. Adding, removing or replacing a factor requires a recent re-authentication (a sign-in or a confirmation in the last 5 minutes). The user receives an email each time a factor is added or removed. When a second factor is mandatory, the last one cannot be removed: the user adds another method first. After 5 consecutive wrong authenticator codes during a re-authentication, codes are refused for 15 minutes.

Reset a user’s MFA

When a user has lost access to every second factor, a platform super admin resets their MFA from AI Governance > Users:
  1. Open the user’s actions menu, then select Reset MFA.
  2. Enter the reason for the reset. It is required and kept in the audit log (gateway.mfa.adminReset event); it is not sent to the user.
  3. Confirm.
All the user’s passkeys and their authenticator app are removed. The user is notified by email and chooses a new second factor at their next sign-in. Super admins cannot reset their own MFA: ask another super admin.

SSO + local on the same deployment

The local/SSO distinction is based on whether the account has a local password:
  • A pure SSO user (created via an identity provider, no local password) is never prompted for a Prisme.ai second factor, and cannot add passkeys: their sign-in security belongs to their identity provider.
  • A local user (password) must complete a second factor when MFA_FORCE_LOCAL is true.
Some SSO provider slugs are reserved:
  • prismeai is the built-in local (password) provider. An SSO provider named prismeai would make its users look like local accounts and force them into a second factor enrollment they cannot complete, locking them out.
  • pwd, otp, hwk, swk and mfa are the authentication method values Prisme.ai records for passwords, codes and passkeys. The gateway refuses to create a provider with one of these slugs, and does not load an existing one: recreate it under another slug.
Use any other slug for federation (for example prisme-saas or prisme-client).

Custom Attribute Mapping

All authentication methods support mapping identity provider attributes to Prisme.ai user properties:
The attributesMapping section in your provider configuration maps provider-specific attributes to standard Prisme.ai fields.
Only firstName, lastName, and email are supported as native fields.Common OIDC Mappings:
Common SAML Mappings:
You can inspect available attributes by examining gateway.login.succeeded events or by reading the {{user}} variable from a test automation.

Password policy

These settings apply to local (email and password) accounts, wherever a password is set: sign-up, password reset, and the password change users make from Settings > Security > Sign-in methods. They follow NIST SP 800-63B-4: a length rule and a list of forbidden passwords, without composition rules or periodic rotation. A new password is refused when it:
  • is shorter than PASSWORD_MIN_LENGTH (default 8, never lower) or longer than PASSWORD_MAX_LENGTH (default 128), counted after Unicode normalization (NFKC);
  • is longer than 72 bytes in UTF-8 while PASSWORD_PEPPER is not set (see Password hashing);
  • contains the email address, its local part, the first name or the last name of the user;
  • is the current password;
  • appears in known data breaches;
  • does not match PASSWORD_VALIDATION_REGEXP, when this deprecated variable is still set.
The console reads both length bounds from the public GET /v2/login/providers route, so the sign-up, reset and change forms always show the rule of your instance.

Breached passwords

PASSWORD_BREACH_CHECK controls how breached passwords are detected:

Password hashing

Passwords are hashed with bcrypt. When PASSWORD_PEPPER is set, new hashes are computed over an HMAC-SHA256 of the password keyed by this secret: bcrypt then takes the whole password into account, beyond its 72-byte limit, and hashes from other leaks cannot be tested against yours. Existing hashes keep working; each password is re-hashed the next time it is set. Without PASSWORD_PEPPER, passwords are hashed with plain bcrypt, which only reads their first 72 bytes. New passwords are then limited to 72 bytes once encoded in UTF-8, whatever PASSWORD_MAX_LENGTH says: 72 characters for ASCII text, fewer for accented or non-Latin scripts. The maximum length served to the console is capped to 72 accordingly, and the gateway logs a warning at startup.
Generate PASSWORD_PEPPER once (for example with openssl rand -base64 32), store it in a Kubernetes secret, and set it before going to production. Never change it or lose it: every password hashed with it would stop working, and the affected users would have to reset their password. Rolling the gateway back to a version that does not know the pepper has the same effect for passwords set in between.

What a password change revokes

When a user changes or resets their password, Prisme.ai:
  • signs out every other session of the user (browsers and paired phones), and refuses any OIDC session, refresh token or authorization code issued before the change, so a revoked browser cannot sign back in silently;
  • emails the user, with a link to reset the password if they did not make the change;
  • emits a gateway.passwordChange.succeeded event (gateway.passwordReset.succeeded for a reset).
Personal access tokens are kept: a reset mostly follows a forgotten password, tokens have a mandatory expiry date, and users can delete theirs from Settings > Security > Access tokens. A change from the settings keeps the session it was made from and requires a recent re-authentication (passkey, password, or password and authenticator code). A reset signs out every session. Accounts that sign in only through SSO cannot change their password nor receive a reset link. Password managers that support it are sent to the change screen by /.well-known/change-password on the console address. For end users, see Change your password.

Troubleshooting

1. Redirect URI MismatchSymptom: Error message about redirect URI not matching during authenticationSolution:
  • Ensure the redirect URI in your IdP exactly matches https://API_URL/v2/login/callback for OIDC/SAML or https://API_URL/v2/login/azure/callback for Microsoft
  • Check for trailing slashes or HTTP vs HTTPS mismatches
2. JWKS Retrieval FailedSymptom: Authentication fails with JWKS errorsSolution:
  • Verify the jwks_uri endpoint is accessible from the Prisme.ai server
  • Check for correct formatting of the JWKS endpoint URL
  • Ensure the signing algorithm is RS256
3. SAML Response Validation FailedSymptom: SAML authentication fails after IdP redirectSolution:
  • Confirm the IdP certificate in the configuration is correct and not expired
  • Verify the IdP is sending responses via HTTP-POST binding
  • Check that the issuer value matches the EntityID expected by the IdP
  • Try adding skipRequestCompression: true and wantAuthnResponseSigned: false SAML options
4. Missing User AttributesSymptom: User logs in successfully but name fields are emptySolution:
  • Check that the attributesMapping configuration matches the actual attribute names provided by your IdP
  • For OIDC, ensure the profile scope is requested if you need name attributes
  • If your IdP issues a minimal id_token (often just sub), the attributes live on its /userinfo endpoint instead: set userinfo_endpoint on the provider and map the claim names it actually returns (see Reading profile claims from the userinfo endpoint)
  • Examine the authentication events to see what claims are actually being received
Event LogsAuthentication issues can be diagnosed by examining events in the Activity view:
  • Look for gateway.login.started events to see authentication attempts
  • Check gateway.login.succeeded events to examine the received user claims
  • Investigate gateway.login.failed events for error details
Configuration TestingYou can validate your SSO configuration by:
  1. Creating a test user in your IdP
  2. Attempting authentication with detailed logs enabled
  3. Examining the request/response data in the Activity logs
Common Error Codes
  • invalid_request: Malformed authentication request
  • unauthorized_client: The client is not authorized for the requested authentication flow
  • access_denied: The resource owner denied the request
  • invalid_token: JWT validation failed
  • invalid_grant: The provided authorization grant is invalid

Security Considerations

Token Validation

  • Always validate JWT signatures using the IdP’s public keys
  • Verify token expiration and issuance times
  • Confirm the audience and issuer claims match your application

Secure Storage

  • Store client secrets securely using environment variables or secrets management
  • Never hardcode secrets in configuration files or source code
  • Rotate secrets periodically according to your security policy

TLS Encryption

  • Ensure all authentication traffic uses HTTPS
  • Configure proper TLS versions and cipher suites
  • Validate certificates in production environments

Access Controls

  • Implement proper RBAC after authentication
  • Don’t assume authenticated users should have access to all resources
  • Regularly audit user access and permissions