ChainLaunch

Pro Feature

SAML 2.0 SSO

SAML 2.0 single sign-on requires ChainLaunch Pro. Learn more about Pro features.

ChainLaunch Pro Feature

SAML 2.0 single sign-on requires ChainLaunch Pro. Learn more about Pro features.

ChainLaunch Pro is a SAML 2.0 Service Provider (SP) that integrates with any compliant Identity Provider (IdP). Use SAML when your organization standardizes on it (common with ADFS, legacy enterprise IdPs) or when OIDC isn't an option. Both protocols share the same role-mapping rules and first-login policies, so an admin only configures provisioning logic once.

This page walks through:

  1. How the flow works (so you can debug it).
  2. Generating SP credentials and registering ChainLaunch with your IdP.
  3. Per-IdP setup (Okta, Microsoft Entra ID / Azure AD, Keycloak, ADFS, Auth0).
  4. Mapping SAML attributes to ChainLaunch roles.
  5. First-login policies.
  6. Single Logout (SLO).
  7. Troubleshooting and security checklist.

How the SAML flow works

ChainLaunch implements SP-initiated SAML with optional IdP-initiated support.

User → ChainLaunch login page
     → 302 redirect to IdP with signed AuthnRequest
     → User authenticates at IdP
     → IdP POSTs signed SAMLResponse to ChainLaunch ACS
     → ChainLaunch verifies signature, audience, conditions, replay
     → ChainLaunch maps assertion → user/role → session cookie
     → Redirect to original RelayState

Under the hood ChainLaunch uses the crewjam/saml library to handle XML signing, signature verification, audience checking, and replay prevention. ChainLaunch never rolls its own SAML crypto.

Step 1 — Generate SP credentials

Each SAML provider in ChainLaunch needs an SP signing keypair (RSA, PKCS#8 or PKCS#1 PEM). The private key signs AuthnRequests and decrypts encrypted assertions. The certificate is published in the SP metadata so the IdP can verify your requests.

Generate one with OpenSSL:

openssl req -x509 -newkey rsa:2048 -keyout sp-key.pem -out sp-cert.pem \
  -days 1095 -nodes \
  -subj "/CN=chainlaunch-sp/O=YourCompany"

Or mint one from the ChainLaunch admin UI: Settings → SSO → Add Provider → SAML → Generate keypair. The private key is encrypted with the master encryption key (see Encryption at rest) before being written to the database — it is never stored in plaintext.

Step 2 — Configure the provider in ChainLaunch

Open Settings → SSO → Add Provider → SAML and fill in:

Field Required Description
Name yes Display name shown on the login button (e.g. Okta)
Entity ID yes Your SP entity ID. Defaults to your ACS URL if blank.
ACS URL yes The Assertion Consumer Service URL: https://chainlaunch.example.com/api/v1/sso/saml/{providerId}/acs
IdP Metadata URL one of URL ChainLaunch fetches at first use (refreshed per-cache load)
IdP Metadata XML one of Pasted XML if your IdP can't expose a public URL
SP Certificate (PEM) yes The cert from Step 1
SP Private Key (PEM) yes The key from Step 1 (PKCS#8 preferred, PKCS#1 accepted)
Group Attribute no SAML attribute that contains group/role names. Defaults to groups.
Default Role no Role assigned when no mapping rule matches. Defaults to VIEWER.
First-login Policy no auto, pending, or reject. See below.

After saving, ChainLaunch publishes the SP metadata at:

GET https://chainlaunch.example.com/api/v1/sso/saml/{providerId}/metadata

Hand this URL (or download the XML) to your IdP admin.

Step 3 — Configure your IdP

Okta

  1. Okta Admin → Applications → Create App Integration → SAML 2.0.
  2. General Settings: name ChainLaunch.
  3. Configure SAML:
    • Single sign-on URL: https://chainlaunch.example.com/api/v1/sso/saml/{providerId}/acs
    • Audience URI (SP Entity ID): same value you set in ChainLaunch.
    • Name ID format: EmailAddress
    • Application username: Email
  4. Attribute Statements — add the attributes ChainLaunch reads:
    Name Format Value
    email Basic user.email
    displayName Basic user.displayName
    groups Basic filter: matches regex chainlaunch-.*
  5. Finish, then on the app's Sign On tab copy the Identity Provider metadata URL and paste it into the ChainLaunch provider's IdP Metadata URL field.
  6. Assign users/groups to the app.

Microsoft Entra ID (Azure AD)

  1. Entra Admin Center → Enterprise applications → New application → Create your own application → "Non-gallery".
  2. Single sign-on → SAML.
  3. Basic SAML Configuration:
    • Identifier (Entity ID): same as ChainLaunch.
    • Reply URL (ACS): your ACS URL.
    • Sign-on URL: https://chainlaunch.example.com/login.
  4. Attributes & Claims — confirm emailaddress is user.mail. Add a groups claim → "Groups assigned to the application" → "sAMAccountName" or "Group ID" depending on your tenant.
  5. Download App Federation Metadata URL and paste into ChainLaunch.
  6. Assign users/groups under Users and groups.

Keycloak

  1. Keycloak Admin → realm → Clients → Create client → SAML.
  2. Client ID: your ChainLaunch entity ID.
  3. Settings:
    • Valid redirect URIs: https://chainlaunch.example.com/*
    • IDP-Initiated SSO URL name: chainlaunch (optional).
    • Master SAML Processing URL: your ACS URL.
    • Sign assertions: ON.
    • Client signature required: ON (matches the cert you generated).
  4. Keys tab → import your SP cert.
  5. Client scopes → role list → Add mapper → Group Membership → name groups, attribute groups, full path OFF.
  6. Realm settings → SAML 2.0 Identity Provider Metadata — copy the URL into ChainLaunch.

ADFS

  1. AD FS Management → Add Relying Party Trust → Claims aware → Import data about the relying party from a file (the SP metadata you downloaded from ChainLaunch).
  2. Issuance Transform Rules — add a rule for each attribute ChainLaunch needs (email, displayName, groups). Use Send LDAP Attributes as Claims (or Send Group Membership as a Claim for groups).
  3. Export your federation metadata: https://adfs.example.com/FederationMetadata/2007-06/FederationMetadata.xml and paste into ChainLaunch.

Auth0

  1. Auth0 Dashboard → Applications → Create Application → Regular Web Application.
  2. Addons → SAML2 Web App → enable.
  3. Application Callback URL: your ACS URL.
  4. Settings JSON — set nameIdentifierFormat, ensure mappings produces email, displayName, and groups claims.
  5. Download metadata from the Usage tab → paste URL into ChainLaunch.

Step 4 — Attribute & role mapping

ChainLaunch reads the following SAML attributes (case-insensitive, and both Name and FriendlyName are matched):

Attribute (any of) Used as
email, mail, emailAddress User email
displayName, name, cn Display name
preferred_username, uid, userPrincipalName Username (falls back to email, then NameID)
Configurable group attribute (default groups) Group membership for role mapping

Subject comes from <Subject><NameID>. ChainLaunch uses it as the stable identity key — even if the email changes later, the same NameID always resolves to the same user.

Role mapping rules

Role mapping uses the same sso_role_mappings table as OIDC. From Settings → SSO → (your provider) → Role Mappings, define ordered rules:

Priority IdP Group ChainLaunch Role
1 chainlaunch-admins ADMIN
2 chainlaunch-operators OPERATOR
3 * VIEWER (catch-all)

Rules are evaluated in order, first match wins. Use * as a catch-all if you want every authenticated user to receive at least VIEWER access.

If no rule matches, ChainLaunch:

  1. Tries the optional RoleAttribute (a single SAML attribute holding a literal role name like ADMIN/OPERATOR/VIEWER).
  2. Falls back to the provider's DefaultRole.
  3. Falls back to VIEWER.

Step 5 — First-login policy

When a user authenticates for the first time and no existing local user matches their NameID or email, the configured FirstLoginPolicy decides what happens:

Policy Behavior
auto (default) Creates the user immediately with the mapped role and lets them in.
pending Creates the user with pending_approval=1 — login is blocked until an admin approves them under Settings → Users → Pending.
reject No user is created. Login fails. Useful when SCIM provisioning is the source of truth.

For high-trust environments paired with SCIM provisioning, set policy to reject so users must be created via SCIM before they can log in.

Single Logout (SLO)

When a SAML provider's metadata advertises a SingleLogoutService endpoint, the ChainLaunch logout button redirects the browser there after invalidating the local session. ChainLaunch does not currently produce a signed LogoutRequest — the browser hits the IdP's SLO URL and the IdP terminates its own session. For most IdPs this is sufficient.

Endpoint:

GET /api/v1/sso/saml/{providerId}/slo

Verifying the integration

# Fetch SP metadata
curl -s https://chainlaunch.example.com/api/v1/sso/saml/1/metadata | xmllint --format -
 
# Trigger SP-initiated login (open in a browser)
open "https://chainlaunch.example.com/api/v1/sso/saml/1/login"
 
# Inspect the audit log for SAML events
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://chainlaunch.example.com/api/v1/audit/sso?provider=saml&limit=20" | jq

Successful flows append login_success and (for new users) user_provisioned events to the SSO audit log — see Audit Logging.

Troubleshooting

Symptom Cause Fix
parse SAML response: invalid signature IdP signs with a key not in the metadata you uploaded Re-export IdP metadata; or rotate the signing cert in the IdP and re-upload
parse SAML response: assertion expired Server clock skew Run NTP on the ChainLaunch host; SAML's NotOnOrAfter is unforgiving
assertion has no NameID IdP isn't including a Subject NameID Configure the IdP to send EmailAddress or Persistent NameID
parse SP key: ... on first login SP private key is encrypted, malformed, or wrong format Regenerate keypair via the admin UI; PKCS#8 PEM works best
User logs in but lands on VIEWER instead of ADMIN Group attribute name mismatch Check that the IdP sends a groups claim (or set Group Attribute to whatever name your IdP uses, e.g. http://schemas.xmlsoap.org/claims/Group)
user pending administrator approval First-login policy is pending Approve under Settings → Users → Pending, or change policy to auto
Repeatedly redirected to IdP Cookie / RelayState mismatch Confirm the ACS URL in the IdP exactly matches what ChainLaunch publishes — including HTTPS and trailing slashes
metadata fetch returned 404 IdP metadata URL is private/unreachable Use IdP Metadata XML field instead and paste the document

Use Settings → SSO → (your provider) → Reload metadata to bust ChainLaunch's metadata cache after rotating IdP keys.

Security checklist

  • SP private key is never committed to source control. ChainLaunch encrypts it at rest with the master key.
  • IdP metadata URL is HTTPS only. Self-signed metadata endpoints are rejected.
  • Disable local auth once SAML is verified working: CHAINLAUNCH_LOCAL_AUTH_DISABLED=true. Always keep one local admin for break-glass.
  • Rotate SP cert before its NotAfter date. Coordinate with the IdP admin so they re-trust the new cert in the same change window.
  • Set FirstLoginPolicy=reject and pair with SCIM when you want full lifecycle control (deprovisioning included).
  • All SAML login attempts are recorded in the audit log — review periodically.

Next steps