Entra SSO

Sign into the OpenSRE web console with Microsoft Entra ID (Azure AD). Pasting a team or admin token still works as break-glass.

This is not the Microsoft Teams bot. Teams needs its own Entra app and TEAMS_* variables. See Integrations.

Which login path to use

OpenSRE has two OIDC-related paths. Use one.

PathWhenWhat to set
Admin → SSO (this guide)Entra Web (confidential) app; Authorization Code without PKCEKeep Helm services.webUi.oidc.enabled false. Do not set WEB_UI_OIDC_*.
Helm / WEB_UI_OIDC_* PKCESPA-style public client with PKCEA separate product path. Leave it off for Entra Web apps.

Tenant ID and client ID live in Admin → SSO (sso_configs). The client secret is env-only: set SSO_CLIENT_SECRET on config-service. Do not put them in git, Helm overlays, or committed docs.

1. Create the Entra app

Azure Portal → Microsoft Entra ID → App registrations → New registration.

  1. Name — for example OpenSRE Web Console
  2. Supported account types — Accounts in this organizational directory only (single tenant)
  3. Redirect URI — platform Web (not SPA):
    • Production: https://<web-ui-host>/api/auth/callback
    • Local Compose: http://localhost:3002/api/auth/callback
  4. Register, then copy:
    • Application (client) ID
    • Directory (tenant) ID

Authentication

App → Authentication:

  • Platform is Web only (no SPA, public client flows disabled)
  • Implicit grant / hybrid: leave ID tokens and Access tokens unchecked
  • Register every origin you will actually use. A mismatch returns AADSTS500112.

Client secret

App → Certificates & secrets → New client secret. Copy the Value once.

API permissions

App → API permissions → Microsoft Graph delegated:

  • openid
  • email
  • profile
  • User.Read

Grant admin consent for the tenant.

Email claim

Entra often omits email from Graph /oidc/userinfo. OpenSRE also accepts preferred_username or upn when they look like emails.

Optional: Token configuration → add optional claim email on ID and access tokens.

2. OpenSRE environment

VariableServicePurpose
WEB_UI_SSO_ORG_IDweb-uiOrg whose SSO config drives the login button. Helm sets this from global.configService.orgId. Compose default: local. If unset, the Microsoft button stays hidden.
WEB_UI_PUBLIC_BASE_URLweb-uiBrowser origin used as Entra redirect_uri. Required when the process binds 0.0.0.0 (Docker/Kubernetes).
WEB_UI_COOKIE_SECUREweb-ui1 on HTTPS. Keep 0 for http://localhost.
SSO_DEFAULT_TEAM_NODE_IDconfig-serviceTeam node SSO sessions attach to (default default).
SSO_CLIENT_SECRETconfig-serviceEntra/OIDC client secret (env only — not in DB or Admin form).
TOKEN_PEPPERconfig-serviceSame pepper used to hash team tokens. SSO cookies are ordinary team tokens.

Local seed (optional): if SSO_AZURE_TENANT_ID and SSO_AZURE_CLIENT_ID are set in .env, demo seed writes SSO config for the local org. Set SSO_CLIENT_SECRET on config-service separately.

Do not reuse Azure Monitor or Teams variables (AZURE_CLIENT_SECRET, TEAMS_APP_PASSWORD).

3. Enable in Admin → SSO

  1. Sign in with the admin token.
  2. Open Admin → SSO.
  3. Provider: Microsoft Entra ID.
  4. Paste tenant ID and client ID.
  5. Confirm Client secret shows SSO_CLIENT_SECRET detected on config-service.
  6. Scopes: openid email profile
  7. Allowed domains: every email domain Entra may return (UPN and mail nickname can differ).
  8. Enable and save.

4. Local Docker Compose

# .env — placeholders only
WEB_UI_SSO_ORG_ID=local
WEB_UI_PUBLIC_BASE_URL=http://localhost:3002
SSO_DEFAULT_TEAM_NODE_ID=default
SSO_CLIENT_SECRET=
SSO_AZURE_TENANT_ID=
SSO_AZURE_CLIENT_ID=
SSO_ALLOWED_DOMAINS=example.com
SSO_SCOPES=openid email profile

Add http://localhost:3002/api/auth/callback on the Entra app. Run make dev and open http://localhost:3002.

If you skip the Azure seed variables, fill Admin → SSO after logging in with the admin token.

5. Kubernetes

Keep services.webUi.oidc.enabled: false.

The Helm chart sets:

  • WEB_UI_SSO_ORG_ID from global.configService.orgId
  • WEB_UI_PUBLIC_BASE_URL from services.webUi.oidc.publicBaseUrl, or https://<ingress.host>

Put SSO_CLIENT_SECRET and TOKEN_PEPPER in the config-service secret. After deploy, paste Entra tenant/client id in Admin → SSO — not in values.yaml.

See self-hosted install for the chart profile.

Smoke test

  • Incognito → Continue with Microsoft Entra ID → land on /team
  • Token login still works

Troubleshooting

SymptomLikely cause
No Microsoft buttonWEB_UI_SSO_ORG_ID unset, or SSO not enabled for that org
AADSTS500112Redirect URI mismatch. Set WEB_UI_PUBLIC_BASE_URL so Docker/Kubernetes does not send http://0.0.0.0:...
Email domain '…' not allowedAdd that domain under Allowed domains
Lands on home with no sessionRebuild web-ui. The callback sets the cookie on a 200 HTML page, then navigates in-browser (Chrome can drop Set-Cookie on a cross-site 302).
Invalid token right after SSOTOKEN_PEPPER on config-service does not match the pepper used to hash the session token
Token exchange 500 / secret not configuredSSO_CLIENT_SECRET missing on config-service