Skip to content

SSO Login Flow

This guide describes the SSO login flow from the perspective of a user signing in to Arbitex. It covers what happens at each step from clicking the SSO button through to an active session in the portal.

For admin configuration of SSO (registering IdPs, setting environment variables, rotating SCIM tokens), see SSO configuration guide.


Arbitex supports three authentication paths. Your organization may have one or more active simultaneously:

Method How you start it Protocol
Entra ID SSO Click Sign in with Microsoft OAuth 2.0 / OpenID Connect
SAML SSO IdP-initiated or via the SAML login link SAML 2.0
Username + password Enter email and password directly Arbitex native

Which methods appear on the login page depends on how your organization’s admin has configured authentication. If your org has enforced SSO-only, the username/password fields are not available.


What happens when you click “Sign in with Microsoft”

Section titled “What happens when you click “Sign in with Microsoft””

The login sequence follows the OAuth 2.0 authorization code flow:

1. You click "Sign in with Microsoft" on the Arbitex login page
2. Arbitex calls: GET /api/auth/oauth/google/authorize
3. Arbitex returns an authorization_url (Microsoft login endpoint)
4. Your browser redirects to the Microsoft login page
5. You authenticate with your Microsoft account (password, MFA, device check — per your org's Entra ID policy)
6. Microsoft redirects your browser back to Arbitex with an authorization code
Callback URL: https://api.arbitex.ai/api/auth/oauth/google/callback
7. Arbitex exchanges the code for an ID token and access token with Microsoft
8. Arbitex validates the ID token:
- Checks the email_verified claim is true
- Verifies the token was issued by your organization's Entra ID tenant
9. If this is your first login, Arbitex creates your account (JIT provisioning)
10. Arbitex issues a session with an access token and refresh token
11. You arrive at the Arbitex portal

If your account does not exist in Arbitex when you first sign in via OIDC, it is created automatically at step 9. Your display name and email are populated from the Entra ID ID token claims. Your initial role is USER. If you need admin access, an org admin must assign it after your first login.

Subsequent logins reuse your existing account — no new account is created on each sign-in.

Step 5 is entirely handled by Microsoft. Arbitex does not control or observe what happens during this step. Your organization’s Entra ID conditional access policies, MFA requirements, and device compliance rules apply here. If you are blocked at the Microsoft login page, contact your IT or Entra ID administrator.

Arbitex requires that the email_verified claim in the Microsoft ID token is true. If Microsoft returns false or omits the claim, Arbitex rejects the login. This is a security requirement — it ensures that the email address in your profile is verified by your IdP. If your login fails with an “email not verified” error, contact your Entra ID administrator.


Service-provider-initiated login begins from the Arbitex login page:

1. You navigate to the Arbitex login page and select SAML login
(or are directed to the SAML login URL by your admin)
2. Arbitex generates a SAML AuthnRequest and redirects your browser to your IdP's SSO URL
3. Your IdP authenticates you (password, MFA, etc. — per your IdP's policy)
4. Your IdP posts a signed SAML Response to the Arbitex ACS URL:
https://api.arbitex.ai/api/auth/saml/acs
5. Arbitex validates the SAML Response:
- Verifies the XML signature against the registered x509 certificate
- Checks the NameID format (emailAddress) and attribute mapping
6. Arbitex matches the email from the SAML assertion to your Arbitex account
7. If this is your first login and JIT provisioning is enabled, your account is created
8. Arbitex issues a session with an access token and refresh token
9. You arrive at the Arbitex portal

Some organizations configure their IdP (Okta, Entra ID enterprise apps, AD FS) to push a SAML assertion directly to Arbitex without a prior AuthnRequest. In this case:

  • You click the Arbitex tile in your IdP dashboard
  • Your IdP posts a SAML Response directly to https://api.arbitex.ai/api/auth/saml/acs
  • The flow resumes from step 5 above

The email address extracted from the SAML assertion is used as your primary identifier. Your org admin configures which SAML attribute carries the email in the IdP configuration’s attribute_mapping field. If the email attribute is missing or misconfigured, login fails. Contact your org admin if you encounter “attribute not found” errors.


After successful SSO login (OIDC or SAML), Arbitex establishes a session:

Token Purpose Behavior
Access token Authenticate API requests Short-lived JWT; includes your user ID, org, role, and session ID
Refresh token Obtain new access tokens Rotated on each use; previous refresh token is invalidated immediately

Your session remains active until:

  • You log out explicitly (access token is blacklisted)
  • Your refresh token expires without renewal
  • An admin invalidates your session
  • Your org’s session limit is reached (older sessions are terminated when the limit is exceeded)

When your access token expires, the client automatically exchanges the refresh token for a new access + refresh pair. The previous refresh token is invalidated at the time of exchange. If you see unexpected logouts, this is typically caused by the refresh token being consumed from two places simultaneously (e.g., two browser tabs with a race condition). Re-authenticating via SSO resolves this.


If your org has MFA enabled on the Arbitex side (in addition to any MFA enforced by your IdP), the login sequence includes a challenge step between credential verification and session issuance:

POST /api/auth/login → returns { mfa_token } instead of { access_token }
POST /api/auth/mfa/verify { mfa_token, totp_code } → returns { access_token, refresh_token }

For SSO (OIDC or SAML) logins, MFA is typically handled entirely by your IdP as part of step 5 (OIDC) or step 3 (SAML). Arbitex-side MFA applies to native username/password accounts. If you are unsure whether your login path requires Arbitex MFA, check with your org admin.

See MFA configuration for setup and backup code recovery.


Your Entra ID account’s email address does not carry the email_verified: true claim. This is an IdP-side configuration issue. Contact your Entra ID administrator.

The redirect URI configured in your Entra ID app registration does not match the Arbitex callback URL:

https://api.arbitex.ai/api/auth/oauth/google/callback

Contact your org admin to verify the App Registration’s redirect URI in Azure Portal.

The x509 certificate registered in Arbitex does not match the certificate your IdP is using to sign assertions. This typically happens after an IdP certificate rotation. Your org admin must update the certificate in the SAML IdP configuration via PUT /api/v1/admin/saml/idp/{idp_id}.

The GET /api/auth/oauth/status endpoint returns { "sso_enabled": false }. The Arbitex Platform API environment variables for OIDC are not set. Contact your platform operator.

If JIT provisioning creates your account in the wrong org, contact your org admin. Account org assignment is determined by the IdP configuration active at the time of your first login.

Your org has a maximum concurrent session limit. When you log in and the limit is exceeded, the oldest session is terminated. If you are being logged out unexpectedly, a device still holding an older session may have been logged out. Re-authenticate on the affected device.


The following diagram shows the detailed authorization code flow for Entra ID OIDC login:

sequenceDiagram
    participant User
    participant Arbitex as Arbitex Platform<br/>(api.arbitex.ai)
    participant Entra as Microsoft Entra ID

    User->>Arbitex: GET /api/auth/oauth/google/authorize
    Note over Arbitex: Generates state token
    Arbitex-->>User: 200 { authorization_url }
    User->>Entra: Redirect to authorization URL
    Entra->>User: Consent screen (if first login)
    User->>Arbitex: POST /api/auth/oauth/google/callback { code, state }
    Arbitex->>Entra: Exchange code for tokens
    Entra-->>Arbitex: id_token + access_token
    Note over Arbitex: Validate OIDC ID token<br/>Verify email_verified claim
    Note over Arbitex: JIT-provision user if new<br/>(email, username from OIDC claims)
    Arbitex-->>User: { access_token, refresh_token, user }

When a new user authenticates via Entra ID OIDC for the first time, Arbitex provisions their account from the OIDC ID token claims:

Field Source
Email email claim (must be verified — email_verified: true)
Username name claim, or email prefix if name is not set
Role USER (default) — admin role must be assigned separately
Password Not set — authentication is SSO-only for JIT-provisioned users

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


  1. In Okta Admin Console, navigate to Applications → Applications → Create App Integration → SAML 2.0.

  2. Configure SAML settings:

    Field Value
    Single sign-on URL (ACS URL) https://api.arbitex.ai/api/auth/saml/acs
    Audience URI (SP Entity ID) Your tenant entity ID from Arbitex admin
    Name ID format EmailAddress
  3. Add attribute statements:

    Name Value
    email user.email
    firstName user.firstName
    lastName user.lastName
    displayName user.displayName
  4. Optionally add a Group Attribute Statement with name groups to sync group memberships.

  5. Download the IdP metadata XML (Entity ID, SSO URL, X.509 certificate).

  6. Register the IdP in Arbitex:

Terminal window
POST https://api.arbitex.ai/api/v1/admin/saml/idp
Authorization: Bearer $ARBITEX_ADMIN_TOKEN
Content-Type: application/json
{
"name": "Okta Production",
"entity_id": "https://your-okta-domain.okta.com",
"sso_url": "https://your-okta-domain.okta.com/app/arbitex/exk.../sso/saml",
"x509_cert": "MIICIjANBgk...",
"attribute_mapping": {
"email": "email",
"first_name": "firstName",
"last_name": "lastName",
"display_name": "displayName",
"groups": "groups"
},
"is_active": true
}
  1. Assign users to the app in Okta — only assigned users can log in via SAML.
  1. In Google Admin Console, navigate to Apps → Web and mobile apps → Add app → Add custom SAML app.

  2. Download the Google IdP metadata (SSO URL, Entity ID, signing certificate).

  3. Configure Service Provider details:

    Field Value
    ACS URL https://api.arbitex.ai/api/auth/saml/acs
    Entity ID Your tenant entity ID from Arbitex admin
    Name ID Basic Information → Primary email
    Name ID format EMAIL
  4. Add attribute mappings: Primary email → email, First name → firstName, Last name → lastName.

  5. Register the IdP in Arbitex with the values from step 2.

  6. Enable the app for the relevant OUs or groups in Google Admin Console.

For any SAML 2.0-compliant IdP (AD FS, OneLogin, PingFederate, Shibboleth, etc.):

Arbitex SP values to provide to your IdP:

Field Value
ACS URL (POST binding) https://api.arbitex.ai/api/auth/saml/acs
SLO URL (optional) https://api.arbitex.ai/api/auth/saml/slo
NameID format urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
Signed assertions Required

Or import SP metadata directly from https://api.arbitex.ai/api/auth/saml/metadata.

Attribute mapping examples (OID format for AD FS / Shibboleth):

{
"email": "urn:oid:0.9.2342.19200300.100.1.3",
"first_name": "urn:oid:2.5.4.42",
"last_name": "urn:oid:2.5.4.4",
"display_name": "urn:oid:2.16.840.1.113730.3.1.241",
"groups": "memberOf"
}

At minimum, the SAML assertion must include either a NameID in email format or an email attribute (or both).