SAML 2.0 sign-in
Sign people in through a SAML 2.0 provider, such as ADFS, Okta or Entra ID, and give them roles from its attributes.
auth: { providers: ['email', saml('corp')] },{ "name": "corp", "kind": "saml", "label": "Contoso", "entityId": "http://www.okta.com/exk1…", "ssoUrl": "https://contoso.okta.com/app/…/sso/saml", "certificates": ["-----BEGIN CERTIFICATE-----…"], "verifiedEmails": true }Startup prints the two things to register at the provider: this App’s entity ID (<public URL>/api/auth/sso/saml2/sp/metadata?providerId=corp, which also serves its metadata) and its assertion consumer service (<public URL>/api/auth/sso/saml2/sp/acs/corp). It needs the @better-auth/sso package, which npm install tablewalk brings unless optional dependencies are skipped.
What you’ll see
Section titled “What you’ll see”- Continue with Contoso on the sign-in card: the entry’s
labelis all the browser learns of it. - A role given at every sign-in from the attributes a role’s
claimsname, as for OpenID Connect.
When to use it, and when not
Section titled “When to use it, and when not”- Use SAML when your organization’s provider offers it and not OpenID Connect, as ADFS often does.
- Use OpenID Connect instead wherever the provider offers both: it needs no certificates to roll over.
Options
Section titled “Options”| Entry key | What it does | Default |
|---|---|---|
entityId, ssoUrl |
The provider’s entity ID (its responses’ Issuer) and its sign-in address | required |
certificates |
One or two PEM certificates it signs with; two while it rolls one over, when its signatures must carry the certificate | required |
attributes |
{ "email": "<attribute>", "name": "<attribute>" }; without email, the address is an emailAddress NameID |
none |
label, verifiedEmails, mfa, tenant, domains, insecure |
As for OpenID Connect; mfa lists AuthnContextClassRef values |
Only sign-in the App starts is taken: a response must answer this App’s own request, once, within a minute of skew. Its assertion must be signed with SHA-256 or stronger. A response with a DOCTYPE, a comment, an encrypted assertion or more than one assertion is refused unread. A person is the provider’s entity ID and a persistent or emailAddress NameID; a transient one is refused. Attributes are the claims a role’s claims read, and saml.tenants() is a tenant’s own provider. Single logout is not offered.
Common mistakes
Section titled “Common mistakes”[identity-provider-unknown]→ add an entry of"kind": "saml"with that name totablewalk.json.[identity-provider-kind]→saml('…')names asamlentry; anoidcone isoidc('…').
Related
Section titled “Related”- Sign in with your identity provider: OpenID Connect, roles from claims, sign-up and linking.
- SCIM provisioning: a directory that adds and removes the people a provider signs in.
- Sign-in: the other providers, accounts and the first administrator.