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.