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.
Which SSO method should I use?
Section titled “Which SSO method should I use?”| Method | Best for | Protocol |
|---|---|---|
| Google OAuth | Google Workspace orgs, developer teams | OIDC |
| Entra ID OIDC | Microsoft 365 orgs, single tenant | OIDC |
| Entra ID SAML | Enterprise with existing SAML IdP federation, Okta bridging | SAML 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.
Google OAuth 2.0 / OIDC
Section titled “Google OAuth 2.0 / OIDC”How Google SSO works
Section titled “How Google SSO works”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.
Prerequisites
Section titled “Prerequisites”- Google Cloud project (free tier is sufficient)
- Google Workspace admin access is not required for basic Google OAuth
- Arbitex platform admin credentials
Step 1: Create a Google Cloud project
Section titled “Step 1: Create a Google Cloud project”If you don’t already have a Google Cloud project for Arbitex:
- Go to console.cloud.google.com.
- Click the project dropdown at the top → New Project.
- 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”- In the Cloud Console, navigate to APIs & Services → Library.
- Search for Google Identity or OAuth 2.0.
- The OAuth 2.0 service is enabled by default on new projects — no manual enablement is needed.
Step 3: Configure the OAuth consent screen
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.
- Navigate to APIs & Services → OAuth consent screen.
- 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.
- 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
- App name:
- Click Save and Continue.
- On the Scopes step, add the following scopes:
openidemailprofile
- Click Save and Continue through the remaining steps.
Key configuration screen — Scopes step:
Add three scopes:
openid,profile. These are the only scopes Arbitex requires. Do not add additional scopes — the platform does not request or use them.
Step 4: Create OAuth 2.0 credentials
Section titled “Step 4: Create OAuth 2.0 credentials”- Navigate to APIs & Services → Credentials → Create Credentials → OAuth client ID.
- Select Web application as the application type.
- Set the name (e.g.,
Arbitex Platform). - Under Authorized redirect URIs, add:
For local development, also add:https://api.arbitex.ai/api/auth/oauth/google/callbackhttp://localhost:8100/api/auth/oauth/google/callback
- Click Create.
- 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_mismatchfrom Google. The URI is case-sensitive.
Step 5: Configure Arbitex platform
Section titled “Step 5: Configure Arbitex platform”Set the following environment variables on the Arbitex Platform API:
| Variable | Value | Notes |
|---|---|---|
GOOGLE_CLIENT_ID | Client ID from Step 4 | Public identifier |
GOOGLE_CLIENT_SECRET | Client Secret from Step 4 | Treat as a credential |
GOOGLE_REDIRECT_URI | https://api.arbitex.ai/api/auth/oauth/google/callback | Must 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.
Step 6: Verify and test
Section titled “Step 6: Verify and test”Check SSO status:
GET https://api.arbitex.ai/api/auth/oauth/statusExpected response:
{ "sso_enabled": true }Initiate a test login:
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", ... }}JIT user provisioning (Google)
Section titled “JIT user provisioning (Google)”| Field | Source |
|---|---|
email claim — must be email_verified: true | |
| Username | name claim, or email prefix if name is absent |
| Role | USER (default) — admin role must be assigned separately |
| Password | Not set — authentication is Google-only |
If the username conflicts with an existing account, a UUID suffix is appended automatically.
Microsoft Entra ID (Azure AD)
Section titled “Microsoft Entra ID (Azure AD)”Arbitex supports two Entra ID integration paths:
| Path | When to use |
|---|---|
| OIDC | Simpler setup; single-tenant organizations |
| SAML 2.0 | Enterprise federation, existing SAML infrastructure, Okta bridging, group claims |
Both support JIT provisioning and group mapping.
Entra ID — OIDC
Section titled “Entra ID — OIDC”Entra ID OIDC uses the same Arbitex OAuth endpoints as Google but points at Microsoft’s OIDC discovery document.
Step 1: Register an app in Entra ID
Section titled “Step 1: Register an app in Entra ID”- Sign in to portal.azure.com.
- Navigate to Microsoft Entra ID → App registrations → New registration.
- Configure:
- Name:
Arbitex Gateway(or your preferred name) - Supported account types:
Accounts in this organizational directory only(single tenant — recommended) orAccounts in any organizational directory(multi-tenant) - Redirect URI: leave blank for now (added in Step 2)
- Name:
- Click Register. Note the Application (client) ID and Directory (tenant) ID.
Step 2: Configure redirect URIs
Section titled “Step 2: Configure redirect URIs”- In the app registration, go to Authentication → Add a platform → Web.
- Add:
https://api.arbitex.ai/api/auth/oauth/google/callback
- Leave Implicit grant and hybrid flows unchecked — Arbitex uses the authorization code flow with PKCE.
- Click Save.
Step 3: Create a client secret
Section titled “Step 3: Create a client secret”- Go to Certificates & secrets → New client secret.
- Set a description and expiry period (12–24 months recommended).
- Click Add. Copy the Value immediately — it is not shown again.
Step 4: Set API permissions
Section titled “Step 4: Set API permissions”Add delegated permissions under Microsoft Graph:
| Permission | Type | Purpose |
|---|---|---|
openid | Delegated | OIDC login |
profile | Delegated | Display name |
email | Delegated | Email address |
Click Grant admin consent for [your tenant] if your tenant requires admin consent for delegated permissions.
Step 5: Configure Arbitex
Section titled “Step 5: Configure Arbitex”Set the same three environment variables as Google OAuth, but the client ID and secret are from Entra:
| Variable | Value |
|---|---|
GOOGLE_CLIENT_ID | Application (client) ID from Step 1 |
GOOGLE_CLIENT_SECRET | Client secret value from Step 3 |
GOOGLE_REDIRECT_URI | https://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.
Entra ID — SAML 2.0
Section titled “Entra ID — SAML 2.0”SAML is recommended when you need group claims, IdP-initiated login, or integration with an existing enterprise SAML federation.
Step 1: Retrieve Arbitex SP metadata
Section titled “Step 1: Retrieve Arbitex SP metadata”GET https://api.arbitex.ai/api/auth/saml/metadataThe 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”- Navigate to Microsoft Entra ID → Enterprise applications → New application.
- Select Create your own application.
- Choose Integrate any other application you don’t find in the gallery (Non-gallery).
- Name it
Arbitex Gatewayand click Create.
Step 3: Configure SAML SSO in Entra
Section titled “Step 3: Configure SAML SSO in Entra”- In the new application, go to Single sign-on → SAML.
- 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
- Identifier (Entity ID):
- Alternatively, configure manually:
- Under Attributes & Claims, configure the attribute statements:
| Claim name | Value |
|---|---|
emailaddress | user.mail |
name | user.displayname |
groups | user.groups (optional — add if you want group mapping) |
The full SAML attribute URIs that Arbitex expects by default:
| Arbitex field | Attribute URI |
|---|---|
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 |
Key configuration screen — Attributes & Claims:
The
emailaddressclaim is required. Thenameandgroupsclaims are optional. Ifnameis absent, Arbitex derives the username from the email prefix. Ifgroupsis absent, group mapping is skipped.
- In the SAML Certificates section, download the Certificate (Base64) — you’ll need this in Step 4.
- Note the Login URL (SSO URL) and Microsoft Entra Identifier (entity ID / issuer).
Step 4: Register the Entra IdP in Arbitex
Section titled “Step 4: Register the Entra IdP in Arbitex”Use the Arbitex admin API to register the IdP:
POST https://api.arbitex.ai/api/admin/saml/idpAuthorization: Bearer arb_live_your-admin-keyContent-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:
# Strip PEM headers and collapse to a single linecat 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.
Step 5: Update the Sign-on URL in Entra
Section titled “Step 5: Update the Sign-on URL in Entra”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.
Step 6: Assign users
Section titled “Step 6: Assign users”In Enterprise applications → Arbitex Gateway → Users and groups, assign the users or groups that should be able to sign in.
Step 7: Test SAML login
Section titled “Step 7: Test SAML login”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.
Group mapping (SAML)
Section titled “Group mapping (SAML)”When the SAML assertion includes a groups attribute, Arbitex synchronizes group memberships:
- The SAML group value (Entra Object ID, e.g.
a1b2c3d4-...) is matched againstGroup.nameandGroup.entra_ad_group_idin Arbitex. - If a match is found, the user is added to the group.
- Group memberships from SAML are additive — existing memberships are not removed.
Configure Arbitex groups to match Entra Object IDs:
PUT https://api.arbitex.ai/api/admin/groups/{group_id}{ "entra_ad_group_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}Troubleshooting
Section titled “Troubleshooting”Google OAuth
Section titled “Google OAuth”503 Google SSO is not configured
Section titled “503 Google SSO is not configured”The GOOGLE_CLIENT_ID environment variable is not set or not readable by the platform pod. Verify:
- The secret exists in Key Vault and the pod has CSI driver access.
- 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.
401 Email address not verified by Google
Section titled “401 Email address not verified by Google”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.
redirect_uri_mismatch (Google error)
Section titled “redirect_uri_mismatch (Google error)”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).
Entra ID SAML
Section titled “Entra ID SAML”401 Invalid SAML response
Section titled “401 Invalid SAML response”SAML Response signature validation failed. Common causes:
- Wrong
x509_certin 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.
401 No email found in SAML assertion
Section titled “401 No email found in SAML assertion”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.
See also
Section titled “See also”- Entra ID SSO admin guide — Entra OIDC configuration reference
- SAML SSO admin guide — SAML IdP management API reference
- Entra ID SCIM provisioning — Automated user and group sync
- Security Overview — Authentication architecture and MFA enforcement