Skip to content

Set Up SSO Authentication

Goal

Replace local username/password authentication with Azure AD (Entra ID) single sign-on using OpenID Connect. By the end of this guide every user will authenticate through Azure AD, and their group memberships will automatically map to Verity RBAC roles.


Prerequisites

Requirement Details
Azure AD tenant Global Admin or Application Admin role
Verity environment Running with the API Gateway accessible
DNS / TLS A public or internal hostname with HTTPS for the redirect URI

1 — Register an Azure AD Application

  1. Open the Azure Portal → App registrations and click New registration.

  2. Fill in:

    Field Value
    Name Verity Access Platform
    Supported account types Accounts in this organisational directory only
    Redirect URI (Web) https://verity.example.com/api/v1/auth/callback
  3. After registration, note the Application (client) ID and Directory (tenant) ID.

  4. Under Certificates & secrets → Client secrets, create a new secret and save its Value immediately.

Secret rotation

Store the client secret in a vault (Azure Key Vault, HashiCorp Vault) and rotate it on a 90-day schedule. Never commit secrets to source control.


2 — Configure API Permissions

Under API permissions, add:

API Permission Type
Microsoft Graph openid Delegated
Microsoft Graph profile Delegated
Microsoft Graph email Delegated
Microsoft Graph GroupMember.Read.All Delegated

Click Grant admin consent for the tenant.


3 — Configure Token Claims

Navigate to Token configuration → Add groups claim:

  • Select Security groups and Groups assigned to the application.
  • Under Customise by token type → ID, choose Group ID.

This ensures the groups claim in the ID token contains the Object IDs of groups the user belongs to.


4 — Create Azure AD Groups

Create (or identify existing) groups to map to Verity roles:

Azure AD Group Object ID (example) Verity Role
Verity-Admins aaa-111-... admin
Verity-Reviewers bbb-222-... reviewer
Verity-Auditors ccc-333-... auditor
Verity-Viewers ddd-444-... viewer

Assign users to the appropriate groups in Azure AD → Groups.


5 — Configure Verity

Set the OIDC environment variables on the API Gateway service:

export VERITY_AUTH_PROVIDER=oidc
export VERITY_OIDC_ISSUER=https://login.microsoftonline.com/<TENANT_ID>/v2.0
export VERITY_OIDC_CLIENT_ID=<CLIENT_ID>
export VERITY_OIDC_CLIENT_SECRET=<CLIENT_SECRET>
export VERITY_OIDC_REDIRECT_URI=https://verity.example.com/api/v1/auth/callback
export VERITY_OIDC_SCOPES="openid profile email"
docker-compose.yml (excerpt)
api-gateway:
  environment:
    VERITY_AUTH_PROVIDER: oidc
    VERITY_OIDC_ISSUER: https://login.microsoftonline.com/${AZURE_TENANT_ID}/v2.0
    VERITY_OIDC_CLIENT_ID: ${AZURE_CLIENT_ID}
    VERITY_OIDC_CLIENT_SECRET: ${AZURE_CLIENT_SECRET}
    VERITY_OIDC_REDIRECT_URI: https://verity.example.com/api/v1/auth/callback
    VERITY_OIDC_SCOPES: "openid profile email"
values.yaml (excerpt)
apiGateway:
  auth:
    provider: oidc
    oidc:
      issuer: https://login.microsoftonline.com/<TENANT_ID>/v2.0
      clientId: <CLIENT_ID>
      redirectUri: https://verity.example.com/api/v1/auth/callback
      scopes: "openid profile email"
      existingSecret: verity-oidc-credentials   # contains client_secret

Group-to-Role Mapping

Configure the mapping in Verity's auth settings:

config/auth.yaml
auth:
  provider: oidc
  oidc:
    group_role_mapping:
      "aaa-111-...": admin
      "bbb-222-...": reviewer
      "ccc-333-...": auditor
      "ddd-444-...": viewer
    default_role: viewer           # fallback for unmapped users
    admin_groups:
      - "aaa-111-..."

Role hierarchy

Verity roles are hierarchical: adminreviewerauditorviewer. A user in multiple groups receives the highest applicable role.


6 — Test the Auth Flow

Login

  1. Open https://verity.example.com in an incognito window.
  2. Click Sign in with SSO — you should be redirected to the Microsoft login page.
  3. Authenticate with an Azure AD account that belongs to one of the mapped groups.
  4. After consent, you are redirected back to the Verity dashboard with an active session.

Token Inspection

Verify the token contains the expected claims:

# Decode the access token (requires jq)
curl -s http://localhost:8000/api/v1/auth/me \
  -H "Authorization: Bearer $ACCESS_TOKEN" | jq .

Expected output:

{
  "sub": "alice@example.com",
  "name": "Alice Johnson",
  "email": "alice@example.com",
  "roles": ["reviewer"],
  "groups": ["bbb-222-..."],
  "exp": 1719907200
}

Token Refresh

Verity automatically refreshes tokens before expiry. Verify by checking the API Gateway logs:

docker compose logs api-gateway | grep "token_refresh"

Logout

Click the user avatar → Sign out. Verity clears the session and redirects to the Azure AD logout endpoint:

https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/logout?post_logout_redirect_uri=https://verity.example.com

7 — Troubleshooting

Symptom Cause Fix
AADSTS50011 — reply URL mismatch Redirect URI in Azure AD does not match Verity's config Ensure VERITY_OIDC_REDIRECT_URI exactly matches the registered redirect URI (including trailing slash)
groups claim missing from token Groups claim not configured or user is in >200 groups Enable the groups claim (Step 3). For large tenants, use the _claim_sources approach with Graph API
User gets viewer instead of expected role Group Object ID mismatch Double-check the Object IDs in group_role_mapping — they are case-sensitive UUIDs
401 Unauthorized after login Client secret expired or misconfigured Regenerate the secret and update the environment variable
Redirect loop on login Cookie domain mismatch or mixed HTTP/HTTPS Ensure the gateway is behind TLS and the cookie Domain attribute matches

Debug logging

Enable verbose auth logs for troubleshooting:

export VERITY_LOG_LEVEL=DEBUG
export VERITY_AUTH_DEBUG=true

Next Steps