Enterprise SSO Endpoints
Create and manage SAML and OIDC identity provider connections, and initiate SSO authentication flows.
Create SSO Connection
POST /api/v1/sso/connections
Headers
Authorization: Bearer <apiKey>X-Bulwark-Tenant: <tenant-id>
Body — SAML
{
"type": "saml",
"name": "Acme Okta",
"domains": ["acme.com"],
"saml": {
"idp_entity_id": "http://www.okta.com/exk...",
"idp_sso_url": "https://acme.okta.com/app/.../sso/saml",
"idp_certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"attribute_mapping": {
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"groups": "http://schemas.xmlsoap.org/claims/Group"
}
},
"jit_provisioning": true,
"group_role_mapping": [
{ "group": "admin-group", "role": "admin" },
{ "group": "dev-group", "role": "member" }
]
}
Body — OIDC
{
"type": "oidc",
"name": "Acme Azure AD",
"domains": ["acme.com"],
"oidc": {
"issuer": "https://login.microsoftonline.com/{tenant-id}/v2.0",
"client_id": "...",
"client_secret": "...",
"scopes": ["openid", "profile", "email", "Groups"]
},
"jit_provisioning": true,
"group_role_mapping": [
{ "group": "00000000-0000-0000-0000-000000000001", "role": "admin" }
]
}
| Field | Required | Description |
|-------|----------|-------------|
| type | Yes | saml or oidc |
| name | Yes | Human-readable connection label |
| domains | Yes | Email domains that route to this connection |
| jit_provisioning | No | Auto-create users on first SSO login (default: true) |
| group_role_mapping | No | Map IdP groups or roles to Bulwark roles |
Response 201
{
"data": {
"connection_id": "sso_01j...",
"type": "saml",
"name": "Acme Okta",
"domains": ["acme.com"],
"status": "active",
"sp_entity_id": "https://api.bulwarkauth.com/api/v1/auth/sso/sso_01j.../metadata",
"sp_acs_url": "https://api.bulwarkauth.com/api/v1/auth/sso/sso_01j.../acs",
"created_at": "2026-03-30T00:00:00Z"
}
}
For SAML connections, use sp_entity_id and sp_acs_url to configure the service provider in your IdP.
List SSO Connections
GET /api/v1/sso/connections
Headers
Authorization: Bearer <apiKey>X-Bulwark-Tenant: <tenant-id>
Response 200
{
"data": [
{
"connection_id": "sso_01j...",
"type": "saml",
"name": "Acme Okta",
"domains": ["acme.com"],
"status": "active",
"created_at": "2026-03-30T00:00:00Z"
}
]
}
Delete SSO Connection
DELETE /api/v1/sso/connections/{id}
Removes the connection. Users who authenticated via this connection are not deleted, but future SSO logins through it will fail.
Headers
Authorization: Bearer <apiKey>X-Bulwark-Tenant: <tenant-id>
Response 200
{
"data": {
"connection_id": "sso_01j...",
"deleted_at": "2026-03-30T14:00:00Z"
}
}
Detect SSO by Email Domain
POST /api/v1/auth/sso/detect
Public endpoint. Given an email address, returns the SSO connection that should handle it. Used by login UIs to redirect directly to the correct IdP without exposing connection IDs.
Headers
X-Bulwark-Tenant: <tenant-id>
Body
{
"email": "[email protected]"
}
Response 200 — Connection Found
{
"data": {
"connection_id": "sso_01j...",
"type": "saml",
"name": "Acme Okta",
"authorize_url": "/api/v1/auth/sso/sso_01j.../authorize"
}
}
Response 404 — No SSO Connection
{
"data": {
"sso_required": false
}
}
Initiate SSO Flow
GET /api/v1/auth/sso/{id}/authorize
Redirects the user's browser to the IdP. For SAML, issues a signed AuthnRequest. For OIDC, redirects to the IdP's authorization endpoint.
Query Parameters
| Parameter | Description |
|-----------|-------------|
| redirect_uri | Where Bulwark should redirect after successful authentication |
| state | Opaque value to prevent CSRF; returned unchanged |
| login_hint | Pre-fill the user's email in the IdP login form |
Response
302 Found — redirect to IdP.
OIDC Callback
GET /api/v1/auth/sso/{id}/callback
Handles the authorization code callback from an OIDC IdP. Exchanges the code for tokens, provisions or updates the user, and issues a Bulwark session.
Query Parameters
| Parameter | Description |
|-----------|-------------|
| code | Authorization code from IdP |
| state | State value from the original authorize request |
| error | Error code if IdP rejected the request |
Response
302 Found — redirect to the redirect_uri supplied at authorize time, with a short-lived session_code query parameter for the client to exchange.
SAML Assertion Consumer Service (ACS)
POST /api/v1/auth/sso/{id}/acs
Receives the SAML response (HTTP POST binding) from the IdP. Validates the assertion signature, processes attribute statements, provisions or updates the user, and issues a Bulwark session.
Body
application/x-www-form-urlencoded
| Field | Description |
|-------|-------------|
| SAMLResponse | Base64-encoded SAML response |
| RelayState | Opaque value passed from the original AuthnRequest |
Response
302 Found — redirect to the application with session.