SSO API
Manage single sign-on configuration programmatically. Configure SAML 2.0 and OpenID Connect providers, verify domains, control enforcement, and inspect SSO sessions through the REST API.
Role requirements
Authentication
Authorization: Bearer <token> header.Get SSO Configuration
/api/sso/team/{teamId}/configRetrieve the current SSO configuration for a team.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
teamId | UUID | Yes | The team ID to retrieve SSO configuration for. |
Response
{
"protocol": "SAML",
"enabled": true,
"enforced": false,
"domainVerified": true,
"verifiedDomains": ["example.com"],
"saml": {
"entityId": "https://idp.example.com/saml/metadata",
"ssoUrl": "https://idp.example.com/saml/sso",
"certificateFingerprint": "AB:CD:EF:12:34:56:78:90",
"signRequests": true,
"forceAuthn": false
},
"oidc": null,
"autoProvisionEnabled": true,
"defaultRole": "VIEWER",
"sessionDurationHours": 8,
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-03-20T14:30:00Z"
}Configure SAML 2.0
/api/sso/team/{teamId}/samlCreate or update the SAML 2.0 SSO configuration for a team.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
entityId | string | Yes | The IdP entity ID (Issuer URL) from your identity provider. |
ssoUrl | string | Yes | The IdP single sign-on URL where SAML authentication requests are sent. |
certificate | string | Yes | The IdP X.509 signing certificate in PEM format. |
signRequests | boolean | No | Whether to sign SAML authentication requests. Default: true. |
forceAuthn | boolean | No | Whether to force re-authentication at the IdP. Default: false. |
attributeMapping | object | No | Custom attribute name overrides for email, firstName, and lastName. |
{
"entityId": "https://idp.example.com/saml/metadata",
"ssoUrl": "https://idp.example.com/saml/sso",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIC...base64...\n-----END CERTIFICATE-----",
"signRequests": true,
"forceAuthn": false,
"attributeMapping": {
"email": "urn:oid:0.9.2342.19200300.100.1.3",
"firstName": "urn:oid:2.5.4.42",
"lastName": "urn:oid:2.5.4.4"
}
}{
"protocol": "SAML",
"entityId": "https://idp.example.com/saml/metadata",
"ssoUrl": "https://idp.example.com/saml/sso",
"certificateFingerprint": "AB:CD:EF:12:34:56:78:90",
"signRequests": true,
"forceAuthn": false,
"createdAt": "2026-03-30T12:00:00Z"
}Configure OpenID Connect
/api/sso/team/{teamId}/oidcCreate or update the OpenID Connect SSO configuration for a team.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
issuerUrl | string | Yes | The OIDC issuer URL. NodeLoom fetches the discovery document from {issuerUrl}/.well-known/openid-configuration. |
clientId | string | Yes | The OAuth 2.0 client ID from your identity provider. |
clientSecret | string | Yes | The OAuth 2.0 client secret. Stored encrypted at rest. |
scopes | string[] | No | OIDC scopes to request. Default: ["openid", "profile", "email"]. |
attributeMapping | object | No | Custom claim name overrides for email, firstName, and lastName. |
{
"issuerUrl": "https://idp.example.com",
"clientId": "0oa1b2c3d4e5f6g7h8i9",
"clientSecret": "your-client-secret",
"scopes": ["openid", "profile", "email"],
"attributeMapping": {
"email": "email",
"firstName": "given_name",
"lastName": "family_name"
}
}{
"protocol": "OIDC",
"issuerUrl": "https://idp.example.com",
"clientId": "0oa1b2c3d4e5f6g7h8i9",
"scopes": ["openid", "profile", "email"],
"createdAt": "2026-03-30T12:00:00Z"
}Enable SSO
/api/sso/team/{teamId}/enableEnable SSO for the team. A valid SAML or OIDC configuration must exist.
{
"enabled": true
}{
"enabled": true,
"protocol": "SAML",
"message": "SSO has been enabled. Users can now authenticate via your identity provider."
}Test before enabling
Enforce SSO
/api/sso/team/{teamId}/enforceEnforce SSO for all team members with a verified domain. Blocks password and social login.
Prerequisites
| Requirement | Description |
|---|---|
| SSO enabled | SSO must be enabled before enforcement can be activated. |
| Domain verified | At least one email domain must be verified. |
{
"enforced": true
}{
"enforced": true,
"verifiedDomains": ["example.com"],
"message": "SSO enforcement is active. All users with @example.com email addresses must authenticate via SSO."
}Lockout risk
SAML Login (Public)
/api/sso/saml/{teamId}/loginInitiate the SAML authentication flow. Redirects the user to the IdP login page.
This endpoint does not require authentication. It generates a SAML AuthnRequest and redirects the browser to the identity provider's SSO URL. After authentication, the IdP posts the SAML response to the ACS endpoint.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
returnTo | string | No | URL to redirect to after successful authentication. Must be a relative path. |
SAML ACS (Public)
/api/sso/saml/{teamId}/acsAssertion Consumer Service. Receives the SAML response from the IdP and creates a session.
This endpoint receives the SAML response posted by the identity provider after successful authentication. NodeLoom validates the assertion signature, extracts user attributes, provisions or links the user account, and creates a session.
Form Parameters
| Parameter | Type | Description |
|---|---|---|
SAMLResponse | string | Base64-encoded SAML response from the identity provider. |
RelayState | string | Optional relay state containing the return URL. |
OIDC Authorize (Public)
/api/sso/oidc/{teamId}/authorizeInitiate the OIDC authorization code flow. Redirects to the IdP authorization endpoint.
This endpoint does not require authentication. It generates a state parameter, PKCE code verifier, and redirects the browser to the identity provider's authorization endpoint.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
returnTo | string | No | URL to redirect to after successful authentication. Must be a relative path. |
OIDC Callback (Public)
/api/sso/oidc/{teamId}/callbackOIDC callback. Exchanges the authorization code for tokens and creates a session.
This endpoint is called by the identity provider after the user authorizes the application. NodeLoom exchanges the authorization code for an access token and ID token, extracts user claims, provisions or links the account, and creates a session.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | Yes | The authorization code from the identity provider. |
state | string | Yes | The state parameter for CSRF protection. Must match the value generated during authorization. |
SSO Check (Public)
/api/sso/check?email=Check if an email address is associated with an SSO-enabled team.
This endpoint is used by the login form to determine whether an email address should be redirected to an SSO login flow. It is rate-limited to prevent email enumeration.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
email | string | Yes | The email address to check for SSO association. |
{
"ssoEnabled": true,
"protocol": "SAML",
"loginUrl": "/api/sso/saml/team_xyz789/login"
}{
"ssoEnabled": false
}Error Responses
All SSO API endpoints return standard error responses with the following structure:
{
"error": "sso_configuration_invalid",
"message": "The SAML certificate has expired.",
"status": 400
}| Status | Error Code | Description |
|---|---|---|
| 400 | sso_configuration_invalid | The SSO configuration is missing required fields or contains invalid values. |
| 401 | unauthorized | The request is not authenticated or the session has expired. |
| 403 | forbidden | The authenticated user does not have Admin role. |
| 404 | team_not_found | The specified team ID does not exist. |
| 409 | sso_already_enabled | SSO is already enabled. Disable it first to change the protocol. |
| 422 | domain_not_verified | Cannot enforce SSO without at least one verified domain. |
| 429 | rate_limited | Too many requests. Check the Retry-After header. |