SAML 2.0
SenseCrypt as a SAML 2.0 identity provider — metadata, bindings, NameID, request signatures, assertion signing and encryption, attribute release, and how the biometric ceremony fits behind SP-initiated SSO.
SenseCrypt is a SAML 2.0 identity provider (IdP). Enterprise applications that speak SAML can federate to SenseCrypt for single sign-on, and the on-device face ceremony sits behind the standard AuthnRequest/Response exchange — the service provider (SP) never sees the biometrics. From the phone's perspective the SAML ceremony is byte-identical to OIDC; only the browser-side entry and exit differ.
Each tenant is its own SAML IdP on its own hostname, with its own signing key (see Multi-tenancy).
Metadata and endpoints
Per tenant, the IdP publishes metadata and a downloadable signing certificate:
| Purpose | Endpoint | API reference |
|---|---|---|
Metadata (application/samlmetadata+xml) | GET {issuer}/v1/idp/saml/metadata | ref |
| Signing certificate (PEM) | GET {issuer}/v1/idp/saml/certificate | ref |
| Single Sign-On (Redirect + POST) | GET|POST {issuer}/v1/idp/saml/sso | redirect, POST |
- entityID is
{issuer}/v1/idp/saml— deliberately a distinct URL under the same host so the OIDC and SAML protocol identities don't collide. - Single Sign-On URL is
{issuer}/v1/idp/saml/sso, advertised for both the HTTP-Redirect and HTTP-POST bindings. - The signing key is per-tenant RSA-2048 with a self-signed X.509 certificate. During a key rotation the metadata publishes multiple
<KeyDescriptor use="signing">certificates (make-before-break), so an SP that re-fetches metadata trusts either side of the switch. The certificate endpoint accepts an optional?kid=to download a specific published cert — including a staged one, to pre-configure an SP before activation.
Point your SP at the metadata URL, or configure the entityID, SSO URL, and certificate manually. The metadata advertises WantAuthnRequestsSigned="false" because request-signature verification is opt-in per SP (below), not IdP-global.
Sign-in flow
- The SP sends an AuthnRequest to
/v1/idp/saml/sso(Redirect or POST binding). IdP-initiated SSO is also supported per SP (?sp=<entityID>), gated on the SP'sallow_idp_initiatedflag. - SenseCrypt validates the request, shows the branded email-entry page, then the QR code, and the user completes the face ceremony — identical to the OIDC flow (see How SenseCrypt works).
- On success, SenseCrypt builds a signed SAML Response and delivers it to the SP's ACS via the HTTP-POST binding — an auto-submitting HTML form that POSTs
SAMLResponse(andRelayState) to your ACS.
The full SP-initiated exchange — from the AuthnRequest through the on-device face proof to the ACS POST — looks like this:
Sign-in for a SAML SP is gated by the SP's attached groups, exactly like an OIDC app: an SP with zero attached groups admits nobody (default-closed). See Authorization.
Assertion Consumer Service (ACS) validation
A requested ACS URL must be on the SP's registered acs_urls allow-list — this is the SAML analog of OIDC's redirect_uri validation, and a mismatch is refused. If the AuthnRequest omits the ACS, the SP's first registered ACS is used.
Request signatures
Verifying the SP's AuthnRequest signature is opt-in per SP: it is enforced only once you register the SP's signing certificate (sp_signing_cert_pem). Both bindings are supported:
- Redirect binding verifies the detached signature over the original percent-encoded query octets (
SAMLRequest=…&RelayState=…&SigAlg=…), per the SAML Bindings spec. - POST binding verifies the enveloped XML-DSig.
Verification always pins to the configured certificate; any <KeyInfo> certificate embedded in the request is ignored. RSA keys are required; accepted SigAlg values are rsa-sha1, rsa-sha256, rsa-sha384, rsa-sha512.
NameID
- Request the
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddressNameID format to receive the user's email as the NameID. - Any other format (persistent, transient, unspecified) yields a stable, opaque identifier for the user (the same per-tenant subject id, not a raw database id).
- A NameID policy requesting a specific format that doesn't match the SP's configured format is rejected with a SAML
InvalidNameIDPolicystatus; an absent or "unspecified" policy falls back to the SP's configured format.
Signing and encryption
The assertion crypto is RSA-based and standards-aligned:
- The assertion is always signed — RSA-SHA256 with SHA-256 digests and exclusive C14N. The outer
<Response>is additionally signed when the SP haswant_response_signedset. There is an invariant that a Response can never be wholly unsigned: if the response isn't signed (or the assertion is encrypted), assertion signing is force-enabled, so there is always something verifiable. - Assertion encryption is optional, enabled by registering the SP's encryption certificate (
encryption_cert_pem). SenseCrypt does sign-then-encrypt into an<EncryptedAssertion>:- Data encryption: AES-256-CBC (
http://www.w3.org/2001/04/xmlenc#aes256-cbc), with a random 16-byte IV and PKCS#7 padding (integrity comes from the enclosed signature). - Key transport: RSA-OAEP with SHA-256 + MGF1-SHA256 (
http://www.w3.org/2009/xmlenc11#rsa-oaep). - Note this is CBC, not GCM.
- Data encryption: AES-256-CBC (
The assertion carries a Bearer SubjectConfirmation (with Recipient = ACS and InResponseTo for SP-initiated requests), an AudienceRestriction of the SP entityID, and a validity window of NotBefore = issue − 30 s to NotOnOrAfter = issue + 300 s (5 minutes). The default AuthnContextClassRef is urn:oasis:names:tc:SAML:2.0:ac:classes:Biometric — the SAML twin of the OIDC acr — and is per-SP overridable to any URI.
Attribute release
Attribute release is gated by the scopes attached to the SP, then renamed by the SP's attribute map:
- A claim is released only when a scope attached to the SP releases it and the user has a value.
- The SP's
attribute_maprenames released claims onto your SAML attribute names. The map can only rename — it can never release an attribute that no attached scope allows. A mapping entry for an unreleased claim is inert and silently dropped, not an error. - The
NameFormatper attribute is configurable viaattribute_name_format:unspecified(theNameFormatattribute is omitted entirely),basic(…attrname-format:basic), oruri(…attrname-format:uri— the last is what Entra ID expects). Multi-valued claims render as repeated<AttributeValue>elements.
See Authorization for how scopes and attributes are modeled.
Per-SP configuration summary
The SP registration controls the crypto and behavior above through these fields:
| Field | Effect |
|---|---|
acs_urls | ACS allow-list (list of {url, binding}) — the redirect_uri analog. |
sp_signing_cert_pem | When set, AuthnRequest signatures are verified (opt-in). RSA only. |
encryption_cert_pem | When set, assertions are encrypted (sign-then-encrypt). RSA only. |
want_assertions_signed | Sign the assertion (default on; force-enabled when needed). |
want_response_signed | Sign the outer <Response> as well. |
allow_idp_initiated | Permit IdP-initiated SSO (?sp=<entityID>). |
name_id_format | The SP's default NameID format. |
attribute_map | Renames released claims onto SAML attribute names (rename only). |
attribute_name_format | unspecified | basic | uri. |
authn_context_class_ref | The asserted AuthnContext (default …:Biometric). |
What is not supported
Verified by absence in the implementation — do not expect these:
- Single Logout (SLO) is not implemented. There is no
SingleLogoutServicein the metadata and noLogoutRequest/LogoutResponsehandling — there is no IdP-side SSO session to propagate a logout from. - HTTP-Artifact binding is not supported. AuthnRequests accept Redirect and POST; Response delivery is POST-only.
- Request-signature verification and assertion encryption require RSA SP certificates (no ECDSA).
- Only Issuer / ID / ACS URL / NameIDPolicy Format are read from the AuthnRequest;
<Extensions>,ForceAuthn/IsPassive, andRequestedAuthnContextare ignored.
Gotchas
- The attribute map renames; it doesn't release. If an attribute isn't coming through, check that a scope releasing it is attached to the SP — the map alone won't surface it.
- Use the
uriNameFormat for Entra ID. Entra expectsattrname-format:uri;unspecifiedomits the format entirely. - No SLO. Sign the user out on your side by clearing your own session; there is no SAML logout to call.
- Encryption is CBC, and requires an RSA encryption cert. Register
encryption_cert_pem(RSA) to enable it; an ECDSA cert won't work.
Set it up
Follow the SAML SSO integration guide to register your SP and configure attribute mapping. Endpoint detail is in the SAML API reference.
Learn more
How SenseCrypt works
Authorization
Multi-tenancy
SAML SSO integration guide
OIDC & OAuth 2.0
SenseCrypt as an OpenID Connect issuer — the Authorization Code flow with PKCE, discovery, PAR, client authentication, grant types, and the token, userinfo, introspection, revocation, and logout endpoints.
SCIM 2.0
Provision users and groups into a SenseCrypt tenant from your identity provider using the SCIM 2.0 protocol, with pending-shell enrollment for biometrics, filtering, bulk, and eager revocation.