description:Set up SAML 2.0 Single Sign-On for SnapOtter. Step-by-step guides for Okta, Azure AD / Entra ID, Google Workspace, and other SAML identity providers.
SnapOtter supports SAML 2.0 for single sign-on. Users can log in via an external identity provider (Okta, Azure AD / Entra ID, Google Workspace, or any standard SAML 2.0 IdP) instead of local username/password authentication.
::: tip Enterprise feature
SAML SSO requires a **team** or **enterprise** license with the `saml_sso` feature. If `SAML_ENABLED=true` is set without a valid license, the SAML routes are silently skipped and a warning is logged.
| `SAML_IDP_SSO_URL` | | IdP's SSO endpoint URL. **Required** when SAML is enabled. |
| `SAML_IDP_CERTIFICATE` | | IdP's X.509 signing certificate in PEM format (the certificate text itself, not a file path). **Required** when SAML is enabled. |
| `EXTERNAL_URL` | | The public URL where SnapOtter is reachable. **Required** when SAML is enabled. |
| `SAML_ENTITY_ID` | `${EXTERNAL_URL}/api/auth/saml/metadata` | SP Entity ID / Audience URI sent to the IdP. |
| `SAML_AUTO_CREATE_USERS` | `true` | Automatically create a local user account on first SAML login. |
| `SAML_AUTO_LINK_USERS` | `false` | Link a SAML identity to an existing local user if the email address matches. |
| `SAML_DEFAULT_ROLE` | `user` | Role assigned to auto-created SAML users. One of `admin`, `editor`, or `user`. |
| `SAML_PROVIDER_NAME` | | Display label for the SAML login button on the frontend (e.g. "Okta", "Azure AD"). If empty, the button says "SAML". |
| `SAML_USERNAME_ATTRIBUTE` | | SAML assertion attribute used as the username. If empty, falls back to the email local-part, then NameID. |
| `SAML_EMAIL_ATTRIBUTE` | `email` | SAML assertion attribute used as the user's email address. |
The server refuses to start if `SAML_ENABLED=true` and any of the three required variables (`SAML_IDP_SSO_URL`, `SAML_IDP_CERTIFICATE`, `EXTERNAL_URL`) are missing.
::: details Security notes
Both `wantAuthnResponseSigned` and `wantAssertionsSigned` are hardcoded to `true`. SnapOtter rejects unsigned or improperly signed SAML responses. Assertions from a trusted IdP are treated as email-verified.
Only SP-initiated login is supported. SnapOtter does not support IdP-initiated (unsolicited) login or Single Logout (SLO). Logging out of SnapOtter does not log the user out of the IdP.
When `SAML_AUTO_CREATE_USERS` is `true` (the default), a local user account is created the first time someone logs in via SAML. The role is set to `SAML_DEFAULT_ROLE`.
The username is derived in this order:
1. The value of the assertion attribute specified by `SAML_USERNAME_ATTRIBUTE` (if set and present)
2. The local-part of the email address (everything before `@`)
3. The SAML NameID
If a username collision occurs, a numeric suffix is appended (e.g. `jane` becomes `jane_2`).
When `SAML_AUTO_LINK_USERS` is `true`, SnapOtter links a SAML identity to an existing local account if the email addresses match. This is useful when you have pre-created user accounts and want them to start using SSO without losing their data.
::: warning
Only enable auto-link if you trust your SAML IdP to verify email addresses. An unverified email from a misconfigured IdP could allow someone to take over another user's account.
If you want to require all users to log in via SAML (or OIDC) and block local password login, enable SSO enforcement:
1. Ensure the `sso_enforcement` enterprise feature is licensed (available on team and enterprise plans).
2. In **Admin Settings > Security**, toggle **SSO Enforcement** on.
3. Set a **break-glass username**: this is the one local account that can still log in with a password, for emergency access if the IdP is unreachable.
When SSO enforcement is active, any local login attempt (except for the break-glass user) returns a 403 error with the message "Local password login is disabled. Please use SSO."
::: tip
Always configure a break-glass username before enabling SSO enforcement. Without it, you could be locked out of SnapOtter if your IdP goes down.
SAML and OIDC can be enabled simultaneously. When both are active, the login page shows separate buttons for each provider (labeled by `SAML_PROVIDER_NAME` and `OIDC_PROVIDER_NAME`). Users can log in with either method.
Both providers share the same auto-create, auto-link, and SSO enforcement settings independently: each has its own `*_AUTO_CREATE_USERS`, `*_AUTO_LINK_USERS`, and `*_DEFAULT_ROLE` variables.
SAML assertions include timestamp conditions (`NotBefore`, `NotOnOrAfter`). If your server clock and the IdP clock are out of sync, assertion validation fails. Run NTP on both machines to keep clocks aligned.
### "SAML is enabled via env but saml_sso enterprise feature is not licensed" {#saml-is-enabled-via-env-but-saml-sso-enterprise-feature-is-not-licensed}
This warning appears in the server logs when `SAML_ENABLED=true` but the license does not include the `saml_sso` feature. Verify your license key and plan. The `saml_sso` feature is available on team and enterprise plans.