Skip to content

SSO Integration Guide

This guide walks through configuring single sign-on (SSO) for Arbitex from end to end, covering both identity provider setup and platform configuration. Two providers are covered:

  • Google OAuth 2.0 / OIDC — suitable for organizations using Google Workspace or personal Google accounts
  • Microsoft Entra ID (Azure AD) — suitable for enterprise organizations; supports both OIDC and SAML 2.0

Both providers use JIT (just-in-time) user provisioning: users are created in Arbitex automatically on their first login, with no pre-staging required.


MethodBest forProtocol
Google OAuthGoogle Workspace orgs, developer teamsOIDC
Entra ID OIDCMicrosoft 365 orgs, single tenantOIDC
Entra ID SAMLEnterprise with existing SAML IdP federation, Okta bridgingSAML 2.0

SAML and OIDC SSO are independent — you can configure both simultaneously and use each for different user populations. API-key-authenticated requests are unaffected by SSO configuration.


sequenceDiagram
participant User
participant Arbitex as Arbitex Platform<br/>(api.arbitex.ai)
participant Google as Google OIDC
User->>Arbitex: GET /api/auth/oauth/google/authorize
Note over Arbitex: Generate state token (stored in Redis, 10-min TTL)
Arbitex-->>User: { authorization_url }
User->>Google: Redirect to authorization URL
Google->>User: Consent screen (first login only)
User->>Arbitex: POST /api/auth/oauth/google/callback { code, state }
Note over Arbitex: Validate state (single-use, CSRF protection)
Arbitex->>Google: Exchange code → id_token + access_token
Note over Arbitex: Validate OIDC ID token<br/>Verify email_verified = true
Note over Arbitex: JIT-provision user if new
Arbitex-->>User: { access_token, refresh_token, user }

CSRF protection is fail-closed: if Redis is unavailable, the OAuth flow is rejected (503) rather than allowing a potentially unsafe login.

  • Google Cloud project (free tier is sufficient)
  • Google Workspace admin access is not required for basic Google OAuth
  • Arbitex platform admin credentials

If you don’t already have a Google Cloud project for Arbitex:

  1. Go to console.cloud.google.com.
  2. Click the project dropdown at the top → New Project.
  3. Name the project (e.g., Arbitex SSO) and click Create.

Step 2: Enable the Google Identity service

Section titled “Step 2: Enable the Google Identity service”
  1. In the Cloud Console, navigate to APIs & ServicesLibrary.
  2. Search for Google Identity or OAuth 2.0.
  3. The OAuth 2.0 service is enabled by default on new projects — no manual enablement is needed.
Section titled “Step 3: Configure the OAuth consent screen”

This screen is shown to users on their first Google login. It must be configured before creating OAuth credentials.

  1. Navigate to APIs & ServicesOAuth consent screen.
  2. Select the user type:
    • Internal — only users in your Google Workspace organization can sign in. Recommended for enterprise deployments.
    • External — any Google account can sign in. Required if you don’t have Google Workspace or want to allow personal accounts.
  3. Fill in the required fields:
    • App name: Arbitex Gateway (or your preferred display name)
    • User support email: your admin email
    • Developer contact information: your admin email
  4. Click Save and Continue.
  5. On the Scopes step, add the following scopes:
    • openid
    • email
    • profile
  6. Click Save and Continue through the remaining steps.

Key configuration screen — Scopes step:

Add three scopes: openid, email, profile. These are the only scopes Arbitex requires. Do not add additional scopes — the platform does not request or use them.

  1. Navigate to APIs & ServicesCredentialsCreate CredentialsOAuth client ID.
  2. Select Web application as the application type.
  3. Set the name (e.g., Arbitex Platform).
  4. Under Authorized redirect URIs, add:
    https://api.arbitex.ai/api/auth/oauth/google/callback
    For local development, also add:
    http://localhost:8100/api/auth/oauth/google/callback
  5. Click Create.
  6. A dialog shows your Client ID and Client Secret. Copy both — the secret is not displayed again after you close the dialog.

Key configuration screen — OAuth client creation:

The redirect URI must exactly match what Arbitex sends in the authorization request. A mismatch produces redirect_uri_mismatch from Google. The URI is case-sensitive.

Set the following environment variables on the Arbitex Platform API:

VariableValueNotes
GOOGLE_CLIENT_IDClient ID from Step 4Public identifier
GOOGLE_CLIENT_SECRETClient Secret from Step 4Treat as a credential
GOOGLE_REDIRECT_URIhttps://api.arbitex.ai/api/auth/oauth/google/callbackMust match Step 4

In Kubernetes deployments, store these in Azure Key Vault or a Kubernetes secret — never in plaintext in ConfigMaps or source code. Restart the Platform API pod after setting the variables.

Check SSO status:

Terminal window
GET https://api.arbitex.ai/api/auth/oauth/status

Expected response:

{ "sso_enabled": true }

Initiate a test login:

Terminal window
GET https://api.arbitex.ai/api/auth/oauth/google/authorize
{
"authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?..."
}

Open the authorization_url in a browser, sign in with a Google account, and verify the callback returns:

{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "bearer",
"user": { "email": "user@example.com", ... }
}
FieldSource
Emailemail claim — must be email_verified: true
Usernamename claim, or email prefix if name is absent
RoleUSER (default) — admin role must be assigned separately
PasswordNot set — authentication is Google-only

If the username conflicts with an existing account, a UUID suffix is appended automatically.


Arbitex supports two Entra ID integration paths:

PathWhen to use
OIDCSimpler setup; single-tenant organizations
SAML 2.0Enterprise federation, existing SAML infrastructure, Okta bridging, group claims

Both support JIT provisioning and group mapping.

Entra ID OIDC uses the same Arbitex OAuth endpoints as Google but points at Microsoft’s OIDC discovery document.

  1. Sign in to portal.azure.com.
  2. Navigate to Microsoft Entra IDApp registrationsNew registration.
  3. Configure:
    • Name: Arbitex Gateway (or your preferred name)
    • Supported account types: Accounts in this organizational directory only (single tenant — recommended) or Accounts in any organizational directory (multi-tenant)
    • Redirect URI: leave blank for now (added in Step 2)
  4. Click Register. Note the Application (client) ID and Directory (tenant) ID.
  1. In the app registration, go to AuthenticationAdd a platformWeb.
  2. Add:
    https://api.arbitex.ai/api/auth/oauth/google/callback
  3. Leave Implicit grant and hybrid flows unchecked — Arbitex uses the authorization code flow with PKCE.
  4. Click Save.
  1. Go to Certificates & secretsNew client secret.
  2. Set a description and expiry period (12–24 months recommended).
  3. Click Add. Copy the Value immediately — it is not shown again.

Add delegated permissions under Microsoft Graph:

PermissionTypePurpose
openidDelegatedOIDC login
profileDelegatedDisplay name
emailDelegatedEmail address

Click Grant admin consent for [your tenant] if your tenant requires admin consent for delegated permissions.

Set the same three environment variables as Google OAuth, but the client ID and secret are from Entra:

VariableValue
GOOGLE_CLIENT_IDApplication (client) ID from Step 1
GOOGLE_CLIENT_SECRETClient secret value from Step 3
GOOGLE_REDIRECT_URIhttps://api.arbitex.ai/api/auth/oauth/google/callback

The platform uses GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET for both Google and Entra OIDC — the variable names are historical. The OIDC discovery document is auto-detected based on the token issuer in the ID token.


SAML is recommended when you need group claims, IdP-initiated login, or integration with an existing enterprise SAML federation.

Terminal window
GET https://api.arbitex.ai/api/auth/saml/metadata

The metadata XML contains:

  • Entity ID: arbitex
  • ACS URL: https://api.arbitex.ai/api/auth/saml/acs (POST binding)
  • SLO URL: https://api.arbitex.ai/api/auth/saml/slo (redirect binding)
  • NameID format: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

Download or copy this XML — you’ll upload it to Entra in the next step.

Step 2: Create an Enterprise Application in Entra

Section titled “Step 2: Create an Enterprise Application in Entra”
  1. Navigate to Microsoft Entra IDEnterprise applicationsNew application.
  2. Select Create your own application.
  3. Choose Integrate any other application you don’t find in the gallery (Non-gallery).
  4. Name it Arbitex Gateway and click Create.
  1. In the new application, go to Single sign-onSAML.
  2. Click Upload metadata file and upload the Arbitex SP metadata XML from Step 1.
    • Alternatively, configure manually:
      • Identifier (Entity ID): arbitex
      • Reply URL (ACS URL): https://api.arbitex.ai/api/auth/saml/acs
  3. Under Attributes & Claims, configure the attribute statements:
Claim nameValue
emailaddressuser.mail
nameuser.displayname
groupsuser.groups (optional — add if you want group mapping)

The full SAML attribute URIs that Arbitex expects by default:

Arbitex fieldAttribute URI
emailhttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
usernamehttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
groupshttp://schemas.microsoft.com/ws/2008/06/identity/claims/groups

Key configuration screen — Attributes & Claims:

The emailaddress claim is required. The name and groups claims are optional. If name is absent, Arbitex derives the username from the email prefix. If groups is absent, group mapping is skipped.

  1. In the SAML Certificates section, download the Certificate (Base64) — you’ll need this in Step 4.
  2. Note the Login URL (SSO URL) and Microsoft Entra Identifier (entity ID / issuer).

Use the Arbitex admin API to register the IdP:

Terminal window
POST https://api.arbitex.ai/api/admin/saml/idp
Authorization: Bearer arb_live_your-admin-key
Content-Type: application/json
{
"name": "Microsoft Entra ID",
"entity_id": "https://sts.windows.net/{tenant_id}/",
"sso_url": "https://login.microsoftonline.com/{tenant_id}/saml2",
"slo_url": "https://login.microsoftonline.com/{tenant_id}/saml2",
"x509_cert": "<base64-cert-without-pem-headers>",
"is_active": true,
"attribute_mapping": {
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"username": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"groups": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groups"
}
}

Replace {tenant_id} with your Azure Directory (tenant) ID.

To prepare the x509_cert value from the downloaded .cer file:

Terminal window
# Strip PEM headers and collapse to a single line
cat arbitex-entra.cer | grep -v "^-----" | tr -d '\n'

Response (201 Created):

{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Microsoft Entra ID",
"entity_id": "https://sts.windows.net/{tenant_id}/",
"is_active": true,
"created_at": "2026-03-12T00:00:00Z"
}

Note the id — this is your IdP UUID used in login URLs.

Go back to the Entra SSO configuration and set the Sign on URL to:

https://api.arbitex.ai/api/auth/saml/login?idp_id={your-idp-uuid}

This enables SP-initiated login from the Arbitex portal.

In Enterprise applicationsArbitex GatewayUsers and groups, assign the users or groups that should be able to sign in.

Open in a browser:

https://api.arbitex.ai/api/auth/saml/login?idp_id={your-idp-uuid}

After authentication, verify the response includes access_token and the correct user email.

When the SAML assertion includes a groups attribute, Arbitex synchronizes group memberships:

  1. The SAML group value (Entra Object ID, e.g. a1b2c3d4-...) is matched against Group.name and Group.entra_ad_group_id in Arbitex.
  2. If a match is found, the user is added to the group.
  3. Group memberships from SAML are additive — existing memberships are not removed.

Configure Arbitex groups to match Entra Object IDs:

Terminal window
PUT https://api.arbitex.ai/api/admin/groups/{group_id}
{
"entra_ad_group_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

The GOOGLE_CLIENT_ID environment variable is not set or not readable by the platform pod. Verify:

  1. The secret exists in Key Vault and the pod has CSI driver access.
  2. The pod restarted after the secret was set (environment variables are read at startup).

503 Redis required for OAuth CSRF protection

Section titled “503 Redis required for OAuth CSRF protection”

REDIS_URL is not configured. Google OAuth requires Redis for CSRF state storage. Set REDIS_URL and restart the platform.

400 Invalid or expired OAuth state parameter

Section titled “400 Invalid or expired OAuth state parameter”

The state parameter is missing or expired (10-minute TTL). Common causes:

  • The user took more than 10 minutes to complete the consent screen
  • Multiple tabs completing the flow simultaneously (state is single-use)
  • Redis was flushed between the authorize and callback calls

Retry the login flow.

Google requires email_verified: true in the OIDC ID token. Personal Gmail accounts are always verified. Google Workspace accounts with custom domains should also be verified. If you see this error, check whether the Google account has a verified email in the Google Account settings.

The redirect URI sent by Arbitex does not match the URI registered in the Google Cloud Console. Verify GOOGLE_REDIRECT_URI exactly matches the authorized redirect URI (including scheme, host, path — case-sensitive).


SAML Response signature validation failed. Common causes:

  • Wrong x509_cert in the Arbitex IdP configuration — update with the certificate from the Entra SAML Certificates section
  • Certificate rotated in Entra but not updated in Arbitex (see Certificate rotation)
  • Clock skew between Arbitex and Entra servers — SAML responses are valid for ~5 minutes

400 No active IdP configuration found for issuer

Section titled “400 No active IdP configuration found for issuer”

The Issuer in the SAML Response does not match the entity_id in Arbitex. The Entra issuer is https://sts.windows.net/{tenant_id}/. Verify this exactly matches the entity_id you registered.

The email attribute is missing. Verify the Attributes & Claims configuration in Entra sends the emailaddress claim using the URI http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress.

Users see “You are not authorized to access this application” (Entra error)

Section titled “Users see “You are not authorized to access this application” (Entra error)”

The user is not assigned to the Arbitex Enterprise Application. Go to Users and groups in the Entra app and assign the user or their group.