Aller au contenu

Single sign-on API

Ce contenu n’est pas encore disponible dans votre langue.

Most administrators set up single sign-on in Settings → Single sign-on, which calls these same endpoints; see Single sign-on. This page is for scripting the configuration and for security reviews.

Who can call them. The settings endpoints need a signed-in person with the sso.manage permission (by default, the Administrator). An API key gets 401 sign in required. Every change is written to the audit log.

Signing in with curl. Sign in once and keep the session cookie, as described in Alerts and cases API: before you start. Then add -b ~/.sp-cookies to every request below.

Settings (sso.manage):

Endpoint Does Success
GET /api/v1/settings/sso The settings, SpeculaPro’s values for the IdP, domains and break-glass administrators. Never the client secret 200
PUT /api/v1/settings/sso Replace the settings. Checks the connection first 200 with the new settings
POST /api/v1/settings/sso/metadata/refresh Fetch the SAML IdP metadata from its URL now 200 with the settings
POST /api/v1/settings/sso/domains Claim an email domain 201 with the domain, or 202 when sent for approval
POST /api/v1/settings/sso/domains/{id}/verify Look for the domain’s DNS TXT record. Never needs approval 200 with the domain
DELETE /api/v1/settings/sso/domains/{id} Stop routing a domain to SSO 204, or 202 when sent for approval
PUT /api/v1/settings/sso/break-glass Replace the list of break-glass administrators 200 with the settings
POST /api/v1/settings/sso/test Start a connection test; open redirect_url in a popup 200 {"redirect_url": …}
GET /api/v1/settings/sso/test/{id} A test’s result, for the administrator who ran it, for 10 minutes 200
GET /api/v1/settings/sso/scim, POST …/scim/tokens, DELETE …/scim/tokens/{id} SCIM provisioning: the base URL and its tokens See the SCIM API

GET /api/v1/settings/sso and GET /api/v1/settings/sso/scim also answer for settings.view (the Auditor), read-only and never with a secret.

Sign-in (no session needed; used by the sign-in page and the IdP):

Endpoint Does
GET /api/v1/auth/sso/workspace?workspace=<slug> {"sso": …, "required": …, "protocol": …}: whether to offer SSO. An unknown workspace answers like one without SSO
POST /api/v1/auth/sso/start Body {"workspace", "email"?, "return_to"?}. Returns {"redirect_url"} and sets the browser-binding cookie. 404 when SSO isn’t offered for the workspace or the email’s domain
GET /api/v1/auth/sso/oidc/callback The OIDC redirect URI
POST /api/v1/auth/sso/saml/{workspace}/acs The SAML ACS URL. Stashes the response and redirects to …/finish
GET /api/v1/auth/sso/saml/{workspace}/finish Validates the stashed response for this browser
GET /api/v1/auth/sso/saml/{workspace}/metadata SpeculaPro’s SP metadata for the workspace (also its SAML entity ID), including the single logout URL. 404 unless the workspace uses SAML
GET, POST /api/v1/auth/sso/saml/{workspace}/slo The SAML single logout URL. Takes the IdP’s signed LogoutRequest (HTTP-Redirect or HTTP-POST), ends the sessions it names and answers the IdP with a signed LogoutResponse; also where the IdP returns the browser after a sign-out started in SpeculaPro. Needs no session cookie. A refused request answers 400 with a reference
GET /api/v1/auth/sso/saml/{workspace}/slo/request?k=<key> For an IdP that takes logout requests only by HTTP-POST: a page that posts the signed LogoutRequest prepared at sign-out to the IdP. The web app sends the browser here when sign-out returns this address as sso_logout_url. The key works once, for 2 minutes; an unknown, used or expired key redirects to /login. Needs no session cookie. 429 when rate limited
POST /api/v1/auth/sso/totp Body {"code"}. Finishes an SSO sign-in that needs the person’s SpeculaPro authenticator code. It takes the authenticator’s code only, not a recovery code

The browser endpoints answer with redirects. A failure goes to /login?sso_error=failed&ref=<request ID> (or sso_error=rate); the reason is in the audit log. How they are protected is in Single sign-on security.

GET returns, and PUT takes, this object. PUT replaces everything, so send the whole object.

Field Meaning
enabled Offer SSO on the sign-in page
protocol oidc or saml
required Everyone signs in with SSO, except break-glass administrators. Needs enabled and a usable break-glass administrator
oidc.issuer Issuer URL. Must be HTTPS
oidc.client_id Client ID
oidc.client_secret Write-only. Stored encrypted, never returned. Leave it out to keep the stored one
oidc.has_client_secret Read-only: whether a secret is stored
oidc.scopes Scopes to request; openid is always added. Default openid, email, profile
oidc.require_email_verified Refuse ID tokens whose email_verified isn’t true. Default true
saml.metadata_url IdP metadata URL, refreshed daily. Must be HTTPS
saml.metadata_xml Write-only. Paste the IdP metadata instead (up to 500,000 characters); this clears metadata_url
saml.idp_entity_id, saml.metadata_fetched_at Read-only: the IdP the metadata describes, and when it was last fetched from the URL
saml.allow_idp_initiated Accept sign-ins started from the IdP’s portal. Default false
saml.email_attribute, saml.name_attribute Attribute names to read; empty uses the common ones
provisioning.jit Create accounts at first sign-in. Default false
provisioning.groups_claim OIDC claim or SAML attribute that lists groups
provisioning.role_mapping_enabled Set roles from groups at every sign-in
provisioning.mappings [{"group": …, "role": …}], up to 200. role is a role key such as analyst or mlro. See Roles
provisioning.default_role Role key when no group matches; empty for none
provisioning.deny_if_no_mapping Refuse when no group matches. Default true
mfa.require_idp_mfa Refuse sign-ins the IdP doesn’t mark as multi-factor
mfa.values amr, acr and AuthnContextClassRef values that mean multi-factor, up to 50. Empty restores the defaults

GET also returns:

Field Meaning
sp.redirect_uri, sp.post_logout_redirect_uri For OIDC registration
sp.entity_id, sp.acs_url, sp.slo_url, sp.metadata_url For SAML registration. sp.slo_url is the single logout URL
domains Each claimed domain: id, domain, verified, verified_at, txt_name, txt_value, created_at
break_glass Each break-glass administrator: id, email, display_name, status, has_password, totp, admin, and usable (active, can manage people, own password and two-factor)
usable_break_glass How many are usable now
domain_verification Whether domains need a DNS TXT record

Before saving, SpeculaPro checks the connection: for OIDC with enabled, it reads the issuer’s discovery document; for SAML, it parses pasted metadata, or saves and then fetches the metadata URL. Turning required on for the first time ends everyone’s password sessions except break-glass administrators’.

Terminal window
curl -s -b ~/.sp-cookies -X PUT -H 'Content-Type: application/json' \
-d '{
"enabled": true, "protocol": "oidc", "required": false,
"oidc": {"issuer": "https://login.example.com", "client_id": "speculapro",
"client_secret": "…", "scopes": ["openid", "email", "profile"],
"require_email_verified": true},
"saml": {"metadata_url": "", "allow_idp_initiated": false, "email_attribute": "", "name_attribute": ""},
"provisioning": {"jit": false, "groups_claim": "groups", "role_mapping_enabled": true,
"mappings": [{"group": "speculapro-analysts", "role": "analyst"},
{"group": "speculapro-mlro", "role": "mlro"}],
"default_role": "", "deny_if_no_mapping": true},
"mfa": {"require_idp_mfa": false, "values": []}
}' \
"$SP/api/v1/settings/sso"

Body {"domain": "acmebank.com.gh"}. Where verification is required, the answer has "verified": false and the record to create: txt_name is _speculapro-challenge.<domain> and txt_value is speculapro-domain-verification=<code>. Without verification, the domain is verified at once.

Claiming and removing a domain are single sign-on changes (sso.config). Where the workspace requires approval for them, send X-Change-Reason: the answer is 202 with the change request, and the TXT record is in the request’s result once it is approved. Only one claim of the same domain can wait at a time.

POST /api/v1/settings/sso/domains/{id}/verify

Section titled “POST /api/v1/settings/sso/domains/{id}/verify”

Looks the TXT record up (5-second timeout) and marks the domain verified when the value matches. If it isn’t found yet, 422.

Body {"user_ids": ["…", "…"]}, up to 20. Replaces the list. Each must hold a role that can manage people. While SSO is required, a list with no usable administrator is refused with 409.

Status Meaning Examples
401 Not signed in, or an API key sign in required
403 Missing sso.manage missing permission sso.manage
404 Unknown domain or test result not found
409 The change would leave no usable break-glass administrator while SSO is required this change would leave no break-glass administrator with a password and two-factor; single sign-on is required in this workspace
422 A setting is invalid or the connection check failed invalid sso configuration: turn single sign-on on before requiring it; …: this deployment's public address is "http://localhost:8080": identity providers would send people back to their own computer. Set SP_SSO_PUBLIC_URL (or SP_NOTIFY_PUBLIC_URL) to the https address people use, then configure single sign-on; …: issuer and client ID are required; …: enter the client secret; …: couldn't read the issuer's OpenID configuration: … (including the discovery document’s jwks_uri must be an https URL, and the same for token_endpoint and authorization_endpoint); …: the IdP metadata isn't valid: …; …: couldn't fetch the IdP metadata: …; …: add the IdP metadata (URL or XML); …: unknown role "…"; …: add at least one break-glass administrator with a password and two-factor before requiring single sign-on; …: … isn't an administrator; break-glass accounts must be able to manage people; …: unknown user in the break-glass list; …: the TXT record … wasn't found yet; DNS changes can take a while to appear; …: … is already listed
429 Too many sign-in attempts too many attempts, try again later