SAML 2.0 Setup

ARX operates as a SAML 2.0 Service Provider (SP), enabling federated single sign-on with any SAML 2.0-compliant identity provider (IdP). This guide covers SP metadata, the Assertion Consumer Service, SP-initiated and IdP-initiated flows, IdP configuration for Okta, Microsoft Entra ID, and OneLogin, attribute mapping, Single Logout, and certificate management.

Endpoints

Endpoint Method Description
/v1/auth/saml/metadata GET Returns the SP metadata XML for IdP configuration.
/v1/auth/saml/login GET Initiates SP-initiated SSO. Accepts org_id or domain query parameter.
/v1/auth/saml/acs POST Assertion Consumer Service. Receives and validates SAML responses.
/v1/auth/saml/slo GET Single Logout endpoint. Handles both IdP-initiated and SP-initiated logout.

SP Metadata

The SP metadata endpoint provides the XML document that IdP administrators need to configure their side of the SAML trust relationship. Access it at:

https://api.arxsec.io/v1/auth/saml/metadata

The metadata contains:

Element Value
Entity ID Configured via SAML_SP_ENTITY_ID. Defaults to https://api.arxsec.io/v1/auth/saml/metadata.
ACS URL https://<ARXSEC_API_URL>/v1/auth/saml/acs (HTTP-POST binding)
SLO URL https://<ARXSEC_API_URL>/v1/auth/saml/slo (HTTP-Redirect binding)
NameID Format urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
AuthnRequests Signed true
Want Assertions Signed true
Signing Certificate Included if SAML_SP_CERT is configured

Most IdPs can consume this URL directly during application setup (often labeled "Upload metadata from URL").

SP-Initiated SSO Flow

In SP-initiated SSO, the user begins the login process at the ARX application.

User          ARX (SP)                    IdP
 |               |                          |
 |-- Login ----->|                          |
 |               |-- AuthnRequest --------->|
 |               |   (HTTP-Redirect)        |
 |               |                          |
 |               |     User authenticates   |
 |               |                          |
 |               |<-- SAML Response --------|
 |               |   (HTTP-POST to ACS)     |
 |               |                          |
 |               |-- Validate assertion     |
 |               |-- JIT provision user     |
 |               |-- Issue session JWT      |
 |<-- Token -----|                          |
  1. The client calls GET /v1/auth/saml/login?org_id=<uuid> or GET /v1/auth/saml/login?domain=<domain>.
  2. ARX looks up the SAML configuration in the sso_configs table by org_id or domain.
  3. ARX fetches the IdP metadata from the stored metadata_url.
  4. ARX extracts the IdP's SingleSignOnService URL (preferring HTTP-Redirect binding, falling back to HTTP-POST).
  5. ARX builds a SAML AuthnRequest XML document with a unique request ID, the ACS URL as AssertionConsumerServiceURL, and the SP entity ID as the Issuer.
  6. The AuthnRequest is DEFLATE-compressed and base64-encoded for the HTTP-Redirect binding.
  7. A cryptographic RelayState token is generated for CSRF protection and stored with the org context.
  8. The user's browser is redirected (HTTP 302) to the IdP's SSO URL with the SAMLRequest and RelayState query parameters.
  9. The user authenticates at the IdP.
  10. The IdP posts a SAML Response to the ACS URL.

IdP-Initiated SSO Flow

In IdP-initiated SSO, the user clicks the ARX application tile in their IdP portal.

  1. The IdP generates a SAML Response containing the user's assertion.
  2. The IdP posts the SAML Response directly to the ACS URL (https://api.arxsec.io/v1/auth/saml/acs).
  3. ARX validates the assertion, extracts attributes, and issues a session JWT.
  4. Since there is no RelayState from an SP-initiated request, ARX identifies the organization from the assertion's Issuer element.

Note: IdP-initiated SSO does not have the CSRF protection provided by the RelayState token. Organizations with strict security policies may choose to disable IdP-initiated SSO and require SP-initiated flows only.

Assertion Consumer Service (ACS)

The ACS endpoint (POST /v1/auth/saml/acs) processes the SAML Response:

  1. Decodes the base64-encoded SAMLResponse from the POST body.
  2. Parses the XML and locates the Assertion element.
  3. Validates the SAML StatusCode is Success.
  4. Extracts the NameID (email address).
  5. Extracts attributes from the AttributeStatement.
  6. Constructs a stable sso_subject in the format saml|<issuer>|<name_id>.
  7. Performs JIT user provisioning or retrieves the existing user.
  8. Generates an HS256 session JWT (8-hour expiration) with audience authenticated.

The ACS response body:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "user": {
    "id": "a1b2c3d4-...",
    "org_id": "e5f6a7b8-...",
    "email": "jane@acme.com",
    "role": "viewer",
    "full_name": "Jane Doe",
    "sso_provider": "saml"
  },
  "saml_attributes": {
    "groups": ["Engineering", "Deployers"],
    "issuer": "https://idp.acme.com",
    "name_id": "jane@acme.com"
  }
}

Session JWT Structure

After successful SAML authentication, ARX issues a session JWT with the following claims:

Claim Value
sub User ID (UUID)
org_id Organization ID
email User's email address
role User's ARX role
aud authenticated
iss ARXSEC_API_URL
exp 8 hours from issuance
auth_method saml

The token is signed with HS256 using SUPABASE_ANON_KEY for compatibility with the standard JWT validation path.

Configuring Okta as the IdP

1. Create a SAML Application

  1. In the Okta Admin Console, navigate to Applications > Create App Integration.
  2. Select SAML 2.0.
  3. In General Settings, enter a name (e.g., "ARX").
  4. In Configure SAML, set the following:
Field Value
Single sign-on URL https://api.arxsec.io/v1/auth/saml/acs
Audience URI (SP Entity ID) https://api.arxsec.io/v1/auth/saml/metadata (or your custom SAML_SP_ENTITY_ID)
Name ID format EmailAddress
Application username Email

2. Configure Attribute Statements

Name Value
email user.email
firstName user.firstName
lastName user.lastName
displayName user.displayName

3. Configure Group Attribute Statements

Name Filter
groups Matches regex .* (or filter to specific groups)

4. Complete Setup

  1. Click Finish and assign the application to users/groups.
  2. Copy the IdP metadata URL from the application's Sign On tab.
  3. In ARX, create an sso_configs row:
INSERT INTO sso_configs (org_id, provider, domain, metadata_url, enabled)
VALUES ('<org-id>', 'saml', 'acme.com', 'https://acme.okta.com/app/exk.../sso/saml/metadata', true);

Configuring Microsoft Entra ID as the IdP

1. Create an Enterprise Application

  1. In the Azure Portal, navigate to Microsoft Entra ID > Enterprise applications > New application > Create your own application.
  2. Select Integrate any other application you don't find in the gallery (Non-gallery).
  3. Under Single sign-on, select SAML.

2. Configure Basic SAML Settings

Field Value
Identifier (Entity ID) https://api.arxsec.io/v1/auth/saml/metadata
Reply URL (ACS URL) https://api.arxsec.io/v1/auth/saml/acs
Sign on URL https://api.arxsec.io/v1/auth/saml/login?domain=acme.com
Logout URL https://api.arxsec.io/v1/auth/saml/slo

3. Configure Attributes & Claims

Claim Name Source Attribute
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name user.displayname
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname user.givenname
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname user.surname
http://schemas.microsoft.com/ws/2008/06/identity/claims/groups Group IDs

4. Complete Setup

  1. Download the App Federation Metadata URL.
  2. Assign users and groups to the application.
  3. Store the metadata URL in the sso_configs table.

Configuring OneLogin as the IdP

1. Add a SAML Application

  1. In the OneLogin Admin Console, navigate to Applications > Add App.
  2. Search for SAML Custom Connector (Advanced).

2. Configure the Connector

Field Value
Audience (EntityID) https://api.arxsec.io/v1/auth/saml/metadata
ACS (Consumer) URL https://api.arxsec.io/v1/auth/saml/acs
ACS URL Validator https://api\\.arxsec\\.io/v1/auth/saml/acs
Single Logout URL https://api.arxsec.io/v1/auth/saml/slo
SAML nameID format Email

3. Configure Parameters

Map the following attributes under the Parameters tab:

Field Name Value
name Name
firstName First Name
lastName Last Name
groups User Groups

4. Complete Setup

Copy the Issuer URL (metadata URL) from the SSO tab and store it in the sso_configs table.

Attribute Mapping

ARX extracts user attributes from the SAML assertion using a priority-based search across common attribute name patterns.

Display Name

Checked in order:

  1. http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
  2. http://schemas.microsoft.com/identity/claims/displayname
  3. displayName
  4. name
  5. cn

If none are found, ARX falls back to constructing a name from givenName + surname attributes using their respective claim URIs (e.g., http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname).

Groups

Checked in order:

  1. http://schemas.xmlsoap.org/claims/Group
  2. http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
  3. groups
  4. memberOf

Group values returned in the assertion can be used with SCIM group-to-role mapping for automated RBAC assignment. See SCIM 2.0 Provisioning for details.

Single Logout (SLO)

ARX supports Single Logout via the /v1/auth/saml/slo endpoint using the HTTP-Redirect binding. The endpoint handles three scenarios:

IdP-initiated logout (LogoutRequest): The IdP sends a SAMLRequest query parameter containing a LogoutRequest. ARX parses the request, extracts the NameID, invalidates the session, and redirects the user to the login page with ?slo=1.

SP-initiated logout response: When the IdP responds to an SP-initiated logout request, it sends a SAMLResponse parameter. ARX processes the response and redirects the user to the login page.

SP-initiated logout start: When called without SAML parameters, ARX terminates the local session and returns a JSON confirmation: {"status": "logged_out", "message": "SAML session terminated"}.

Certificate Configuration

SP Certificate (Signing)

To enable AuthnRequest signing, configure the SP certificate and private key:

SAML_SP_CERT=-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----
SAML_SP_KEY=-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----

When SAML_SP_CERT is configured, the certificate is included in the SP metadata under a <md:KeyDescriptor use="signing"> element. IdPs that require signed requests will use this certificate for verification.

IdP Certificate (Verification)

The IdP's signing certificate is extracted automatically from the IdP metadata XML. ARX fetches the metadata from the configured metadata_url and parses the X509Certificate element from the IDPSSODescriptor. No manual certificate configuration is required on the ARX side as long as the IdP publishes its metadata at a reachable URL.

SSO Configuration Table

Each organization's SAML configuration is stored in the sso_configs table:

Field Description
org_id The organization UUID
provider Must be saml
domain The organization's email domain (used for domain-based lookup)
metadata_url The IdP's metadata XML URL
enabled Boolean. Set to false to disable SAML without deleting the configuration

Environment Variables

Variable Required Default Description
SAML_SP_ENTITY_ID No https://api.arxsec.io/v1/auth/saml/metadata The SP entity ID used in AuthnRequests and metadata
SAML_SP_CERT No None PEM-encoded SP signing certificate
SAML_SP_KEY No None PEM-encoded SP private key
ARXSEC_API_URL Yes http://localhost:8000 Base URL for constructing ACS and SLO URLs
SUPABASE_ANON_KEY Yes -- Used to sign session JWTs after SAML authentication

Troubleshooting

Symptom Cause Resolution
404 No SAML configuration found No sso_configs row for the org/domain Insert a row with provider=saml, enabled=true, and the correct org_id or domain.
400 SAML configuration missing metadata_url Config row exists but metadata_url is null Update the sso_configs row with the IdP's metadata URL.
502 Failed to fetch IdP metadata Metadata URL unreachable Verify the URL is correct and accessible from the ARX API server (15-second timeout).
502 IdP metadata missing IDPSSODescriptor Malformed or incomplete IdP metadata Verify the metadata URL returns a valid SAML IdP metadata document.
400 SAML Response missing Assertion Malformed SAML response Check the IdP configuration and ensure the user is assigned to the application.
401 SAML authentication failed StatusCode is not Success Review the IdP logs for authentication errors (user not assigned, MFA failure, etc.).
400 SAML assertion missing email NameID not set to email format Configure the IdP to use EmailAddress as the NameID format.
Attribute mapping issues IdP sends non-standard attribute names Enable debug logging and inspect the saml_attributes field in the ACS response.