SAML 2.0 Enterprise Cloud
SAML 2.0 SSO is part of the Enterprise and Cloud editions. The free Community edition supports OAuth SSO (Google, Okta, OneLogin, Azure AD / B2C, Auth0), magic-link email, and built-in credentials login — see the Authentication index. The SAML-specific features (IdP-driven user provisioning, group-to-role mapping, role synchronization on every login) are what's gated. See Editions.
Description
Integrate NudgeBee with any SAML 2.0 compliant Identity Provider (IdP) to enable Single Sign-On (SSO) for your organization. This allows users to authenticate using their existing corporate credentials through providers such as Okta, Azure AD and others.
Unlike the OAuth-based integrations (e.g., Okta OAuth, Google OAuth), the SAML integration uses the SAML 2.0 protocol directly. This provides additional capabilities such as automatic user provisioning, group-to-role mapping, and role synchronization on every login.
This guide is applicable to both On-Prem and SaaS deployments.
How It Works
NudgeBee acts as a SAML Service Provider (SP). When a user clicks the SSO login button, NudgeBee redirects them to your Identity Provider for authentication. After successful authentication, the IdP sends a signed SAML assertion back to nudgebee, which validates it and creates a session.
Prerequisites
Before configuring SAML, ensure you have:
- A SAML 2.0 compliant Identity Provider (Okta, Azure AD, OneLogin, etc.)
- Admin access to your IdP to create a SAML application
- Admin access to your NudgeBee deployment to set environment variables
- The NudgeBee base URL (e.g.,
https://app.yourdomain.com)
Configuration
Required Environment Variables
| Variable | Description | Example |
|---|---|---|
SAML_ENABLED | Enable SAML authentication. Set to true to activate. | true |
SAML_ENTRY_POINT | The SSO URL of your Identity Provider (IdP login endpoint). | https://yourorg.okta.com/app/app-id/sso/saml |
SAML_ISSUER | The Entity ID that NudgeBee presents when it asks your IdP to authenticate someone. It identifies NudgeBee, not the IdP, and it must match the identifier registered for the NudgeBee application at your IdP. | https://app.yourdomain.com |
SAML_CERT | The IdP's X.509 signing certificate in PEM format. Used to verify SAML assertion signatures. | See Certificate Setup |
NEXTAUTH_URL | The base URL of your NudgeBee application. Used to construct the ACS callback URL unless SAML_CALLBACK_BASE is set. | https://app.yourdomain.com |
NEXTAUTH_SECRET | A secret key used to sign session tokens. Must be a strong random string — generate one with openssl rand -base64 32. | <your-random-secret> |
SAML_ISSUER identifies NudgeBee, not your IdPThis is the single most common misconfiguration. SAML_ISSUER is sent to your identity provider so it can recognise which application is asking; it is not the provider's own Entity ID. Your provider looks up the NudgeBee application by this exact string, so it must match the identifier registered there — on AD FS, the relying party identifier. SAML_AUDIENCE normally holds the same value, and defaults to SAML_ISSUER when you leave it unset.
Optional Environment Variables
| Variable | Description | Default |
|---|---|---|
SAML_AUDIENCE | The audience NudgeBee expects to find in the assertion. This is also the NudgeBee application's identifier at your IdP, so it is normally the same value as SAML_ISSUER. | SAML_ISSUER |
SAML_CALLBACK_BASE | Base URL used to build the ACS callback URL (<base>/api/auth/saml/acs). Set it when NEXTAUTH_URL is unset or differs from the URL registered at your IdP. | NEXTAUTH_URL |
SAML_GROUP_MAPPING | JSON object mapping IdP group names to NudgeBee roles. | {} (no mapping) |
SAML_SYNC_ROLES_ON_LOGIN | Sync user roles from SAML groups on every login. | true |
SAML_REMOVE_OLD_ROLES | Remove roles not present in the current SAML assertion during sync. | true |
SAML_INCLUDE_UNMAPPED_GROUPS | Pass through IdP groups that are not in the mapping as-is. | false |
SAML_SP_PRIVATE_KEY | PEM private key used to sign outgoing authentication requests. Setting it turns signing on — see Signed Authentication Requests. | Not set (requests are unsigned) |
SAML_SP_CERT | The certificate matching SAML_SP_PRIVATE_KEY, in PEM format. Published in SP metadata. | Not set |
Setting the Variables with Helm
Put the SAML_* variables under additional_env_vars in your Helm values, not under nudgebee_secret. nudgebee_secret accepts only a fixed list of keys, and an unknown key such as SAML_ENABLED makes the Helm render fail. NEXTAUTH_URL and NEXTAUTH_SECRET stay under nudgebee_secret.
additional_env_vars:
SAML_ENABLED: "true"
SAML_ENTRY_POINT: "https://yourorg.okta.com/app/app-id/sso/saml"
SAML_ISSUER: "https://app.yourdomain.com"
SAML_CERT: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
If you use nudgebee_secret.existingSecretName, additional_env_vars isn't rendered; put the SAML_* keys in that existing Secret instead.
Certificate Setup
The SAML_CERT variable should contain your IdP's X.509 signing certificate. You can provide it with or without the PEM header/footer — NudgeBee will normalize it automatically.
# With PEM headers (recommended)
SAML_CERT="-----BEGIN CERTIFICATE-----
MIIDpDCCAoygAwIBAgIGAX...
-----END CERTIFICATE-----"
# Without PEM headers (also accepted)
SAML_CERT="MIIDpDCCAoygAwIBAgIGAX..."
You can typically download this certificate from your IdP's SAML application settings page.
Signed Authentication Requests
Some Identity Providers reject sign-in requests that are not digitally signed. Microsoft AD FS is the common case: when its relying party trust has Require signed SAML authentication requests turned on, the browser lands on an AD FS error page reading MSIS7085: The server requires a signed SAML authentication request but no signature is present.
SAML_SP_PRIVATE_KEY and SAML_SP_CERT are optional and unset by default. With neither set, NudgeBee sends unsigned authentication requests, which is how it has always behaved and what most identity providers accept. Setting SAML_SP_PRIVATE_KEY is what switches signing on; SAML_SP_CERT only publishes the matching certificate in SP metadata. If your sign-in works today, you do not need either of them.
Starting from your IdP's portal still works while this is unconfigured, because that flow sends no authentication request at all. Only the SSO button on the NudgeBee sign-in page fails.
Step 1 — Generate a signing key pair
Run this wherever you manage your deployment's secrets. The private key stays in your environment; NudgeBee never needs a copy.
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-keyout nudgebee-saml-sp.key \
-out nudgebee-saml-sp.crt \
-subj "/CN=nudgebee-saml-sp"
| File | Contains | Used for |
|---|---|---|
nudgebee-saml-sp.key | Private key. Keep it secret. | The SAML_SP_PRIVATE_KEY variable |
nudgebee-saml-sp.crt | Public certificate. | The SAML_SP_CERT variable, and upload to your IdP |
A certificate issued by your own internal CA works just as well — NudgeBee does not check who issued it. A long validity period is recommended so that rotation does not become a recurring task.
Step 2 — Give the certificate to your IdP
Do this before setting the environment variables. If NudgeBee starts signing while your IdP does not yet hold the certificate, sign-in fails signature validation instead.
For AD FS, in AD FS Management:
- Open Relying Party Trusts and select the NudgeBee trust.
- Open Properties → Signature → Add… and select
nudgebee-saml-sp.crt. - On the Advanced tab, confirm the secure hash algorithm is SHA-256. NudgeBee signs with RSA-SHA256, which is the AD FS default.
For other providers, look for a "request signing", "verification certificate", or "validate signatures" setting on the SAML application.
Step 3 — Set the environment variables
SAML_SP_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0...
-----END PRIVATE KEY-----"
SAML_SP_CERT="-----BEGIN CERTIFICATE-----
MIIDpDCCAoygAwIBAgIGAX...
-----END CERTIFICATE-----"
What the key variable accepts:
- RSA keys only. Requests are signed with RSA-SHA256, so an elliptic-curve key is rejected at startup rather than producing a signature your IdP cannot check.
- Both
BEGIN PRIVATE KEYandBEGIN RSA PRIVATE KEYforms, and the base64 body on its own, the same waySAML_CERTworks. - Indented values and Windows line endings, both of which a YAML block or a secret manager can introduce.
- Not a passphrase-protected key, and not a key collapsed onto one line with
\nwritten out as two characters. Both are common when a key is pasted into a values file, and both are refused with the variable named.
Restart the application, then confirm signing is active:
curl -s https://app.yourdomain.com/api/auth/saml/health | grep -o '"requestSigning":{[^}]*}'
A key NudgeBee cannot read disables SAML rather than quietly sending unsigned requests, because an unsigned request is exactly what your IdP is rejecting. The health endpoint names the offending variable in that case, and also reports when SAML_SP_CERT does not belong to SAML_SP_PRIVATE_KEY — a mismatched pair signs successfully here while your IdP rejects every request it cannot verify.
Rotating the signing certificate
Replace the certificate in this order so that sign-in keeps working throughout:
- Generate a new key pair.
- Add the new certificate to your IdP alongside the existing one. AD FS accepts more than one signing certificate per trust.
- Update
SAML_SP_PRIVATE_KEYandSAML_SP_CERT, then restart. - Remove the old certificate from your IdP.
An expiring signing certificate is reported by the health endpoint 30 days ahead.
NudgeBee Service Provider Details
When creating a SAML application in your IdP, you will need to provide the following NudgeBee SP details:
| Field | Value |
|---|---|
| ACS URL (Assertion Consumer Service) | {NEXTAUTH_URL}/api/auth/saml/acs |
| Entity ID / Audience | The same value you set for SAML_ISSUER and SAML_AUDIENCE (e.g., https://app.yourdomain.com). Whatever you enter here is what your IdP will match incoming requests against. |
| NameID Format | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress |
| Sign-on URL | {NEXTAUTH_URL}/api/auth/saml/login |
| SP Metadata URL | {NEXTAUTH_URL}/api/auth/saml/metadata |
If your IdP can import a Service Provider from a URL, point it at the metadata URL instead of entering the fields by hand. The metadata carries the ACS URL, the entity id, the NameID format, and the request-signing certificate when one is configured.
Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/auth/saml/login | GET | Initiates the SAML login flow (SP-initiated SSO) |
/api/auth/saml/acs | POST | Assertion Consumer Service — receives the SAML response from the IdP |
/api/auth/saml/metadata | GET | Service Provider metadata for import into your IdP |
/api/auth/saml/health | GET | Returns SAML configuration status and certificate health |
SAML Attribute Mapping
NudgeBee automatically extracts user attributes from the SAML assertion. The following attribute names are supported:
Email (required)
NudgeBee looks for the user email in this order:
emailmailnameID(fallback)
Display Name (optional)
displayNamenamefirstName+lastName(combined)
Groups / Roles (optional)
NudgeBee checks for group information using these attribute names:
groupsGroupmemberOfrolesRolehttp://schemas.xmlsoap.org/claims/Grouphttp://schemas.microsoft.com/ws/2008/06/identity/claims/groups
Configure your IdP to send one of the above group attributes in the SAML assertion to enable automatic role mapping.
Group-to-Role Mapping
NudgeBee can automatically map IdP groups to NudgeBee roles on every login. This ensures users always have the correct permissions based on their IdP group membership.
Configuration
Set the SAML_GROUP_MAPPING environment variable to a JSON object where keys are IdP group names and values are NudgeBee role names:
SAML_GROUP_MAPPING='{"idp-admins":"tenant_admin","idp-developers":"tenant_admin","idp-viewers":"tenant_admin_readonly"}'
Available NudgeBee Roles
| Role | Description |
|---|---|
tenant_admin | Full access to the tenant |
tenant_admin_readonly | Read-only access to the tenant |
Behavior Options
SAML_SYNC_ROLES_ON_LOGIN=true(default): User roles are updated from the SAML assertion on every login. This ensures roles stay in sync with your IdP.SAML_REMOVE_OLD_ROLES=true(default): Roles that are no longer present in the SAML assertion are removed. Set tofalseto only add new roles without removing existing ones.SAML_INCLUDE_UNMAPPED_GROUPS=true: IdP groups that are not listed inSAML_GROUP_MAPPINGare passed through as-is. Useful when your IdP group names already match NudgeBee role names.
Example
If a user belongs to IdP groups ["developers", "viewers"] and your mapping is:
{
"developers": "tenant_admin",
"viewers": "tenant_admin_readonly"
}
User Provisioning
SAML integration supports automatic user provisioning — users are created in NudgeBee on their first SAML login. No pre-registration is required.
How Provisioning Works
- Existing user found by SAML account: User is logged in directly.
- Existing user found by email: The SAML account is linked to the existing user.
- No existing user: A new user is created automatically.
On-Prem Deployments
- The user is created under the tenant specified in your license.
- New users get the role set in
AUTH_DEFAULT_ROLE. - When
SAML_GROUP_MAPPINGis set and no group matches, role sync falls back to the tenant'sauth_default_role, thenAUTH_DEFAULT_ROLE.
SaaS Deployments
- The user's email domain is matched to a tenant via the
allowed_domainstenant attribute. - The default role is determined by the
auth_default_roletenant attribute.
Health Check
NudgeBee provides a health check endpoint to monitor your SAML configuration and certificate status:
GET /api/auth/saml/health
Response:
{
"enabled": true,
"status": "healthy",
"certificate": {
"expired": false,
"expiringSoon": false,
"expiresAt": "2025-12-01T00:00:00.000Z",
"daysUntilExpiry": 365
},
"requestSigning": {
"enabled": true,
"certificate": {
"expired": false,
"expiringSoon": false,
"expiresAt": "2035-09-01T00:00:00.000Z",
"daysUntilExpiry": 3650
}
},
"config": {
"entryPoint": "https://yourorg.okta.com/app/.../sso/saml",
"issuer": "https://app.yourdomain.com",
"callbackUrl": "https://app.yourdomain.com/api/auth/saml/acs"
},
"messages": []
}
requestSigning.enabled is false on deployments that have not configured signed authentication requests, and the certificate block is then absent. A signing certificate that cannot be read is reported as requestSigning.error.
Status values:
healthy— Certificate is valid with more than 30 days remaining.warning— Certificate expires within 30 days. Renew soon.error— Certificate has expired, or a configured signing key cannot be read. SAML login will fail.
Troubleshooting
| Issue | Possible Cause | Solution |
|---|---|---|
| SAML login button does not appear | SAML_ENABLED is not set to true | Set SAML_ENABLED=true and restart the application |
| "SAML not configured" error | Missing required environment variables | Ensure SAML_ENTRY_POINT, SAML_ISSUER, SAML_CERT, and NEXTAUTH_URL (or SAML_CALLBACK_BASE) are all set |
| Signature validation fails | Incorrect or expired IdP certificate | Download a fresh certificate from your IdP and update SAML_CERT |
| User gets "not allowed" error | User account is suspended in NudgeBee | Check the user's status in NudgeBee and reactivate if needed |
| Groups/roles not syncing | Group attribute not sent in assertion | Verify your IdP is configured to send group attributes (see SAML Attribute Mapping) |
| Groups/roles not mapping correctly | Incorrect SAML_GROUP_MAPPING value | Ensure the JSON is valid and the IdP group names match exactly (case-sensitive) |
| "Invalid session data" error | Session token expired (took >60 seconds) | Check network latency between IdP and NudgeBee; ensure clocks are synchronized |
| User created but wrong role | Default role misconfigured | On-Prem: check AUTH_DEFAULT_ROLE. SaaS: check the tenant's auth_default_role attribute |
| Certificate expiry warning | IdP certificate is expiring soon | Download a new certificate from your IdP and update SAML_CERT; use /api/auth/saml/health to monitor |
IdP reports that a signed authentication request is required (AD FS MSIS7085) | The IdP requires signed requests and NudgeBee is not configured to sign them | Configure Signed Authentication Requests. To confirm the diagnosis first, note that signing in from the IdP portal still works while the SSO button does not |
SAML login button disappears right after setting SAML_SP_PRIVATE_KEY | The key is malformed, or is protected by a passphrase | Check /api/auth/saml/health — it names the variable. Re-export the key in PEM form without a passphrase |
| Signature validation fails only after enabling request signing | The IdP does not hold the matching certificate, or holds an older one | Upload nudgebee-saml-sp.crt to the IdP and confirm the hash algorithm is SHA-256 |
Metadata URL returns SAML_SP_CERT is required | A signing key is set without its certificate | Set SAML_SP_CERT to the certificate matching SAML_SP_PRIVATE_KEY |
| Health reports the certificate does not match the key | The key was regenerated and the old certificate was left in place | Re-export the certificate from the current key, upload it to the IdP, then update SAML_SP_CERT |
IdP reports an unknown or unsupported application (AD FS MSIS7007) | SAML_ISSUER does not match the identifier registered for NudgeBee at the IdP | Set SAML_ISSUER to that identifier — see the warning under Required Environment Variables |
| Sign-in fails on an audience mismatch | SAML_AUDIENCE is unset, so it fell back to SAML_ISSUER, or the two hold different values | Set both to the NudgeBee application's identifier at your IdP |
Notes
- SAML authentication supports automatic user provisioning — users do not need to be pre-created in NudgeBee.
- Multiple authentication providers can be enabled alongside SAML (e.g., Google OAuth + SAML).
- The SAML integration uses SP-initiated SSO. The login flow starts from the NudgeBee sign-in page.
- If you have any issues or require more details, please contact our support.