Skip to content

Set up OIDC SSO#

Goal: connect swarm to your identity provider (Google Workspace, Okta, Azure AD, Auth0). Time: ~15 minutes.

Why#

  • Identity hygiene — users sign in with their corporate account, no separate swarm passwords to manage
  • Audit — every action is attributable to a real user identity
  • Policy — role-based access control ties back to IdP groups
  • Compliance — HIPAA / SOC 2 / RBI FREE-AI all want this

1. Register swarm with your IdP#

Create an OpenID Connect application in your IdP:

  • Redirect URI: https://<your-swarm-url>/api/v1/auth/oidc/callback
  • Scopes: openid email profile
  • Grant types: authorization_code

The IdP gives you three values to copy: client ID, client secret, issuer URL (aka discovery endpoint).

  1. console.cloud.google.comAPIs & Services → Credentials → Create credentials → OAuth client ID
  2. Application type: Web application
  3. Authorized redirect URI: https://<your-swarm>/api/v1/auth/oidc/callback
  4. Issuer URL is always: https://accounts.google.com
  1. Okta Admin → Applications → Create App Integration → OIDC - OpenID Connect → Web Application
  2. Sign-in redirect URI: https://<your-swarm>/api/v1/auth/oidc/callback
  3. Issuer URL: https://<your-org>.okta.com
  1. Entra ID → App registrations → New registration
  2. Redirect URI: https://<your-swarm>/api/v1/auth/oidc/callback (Web platform)
  3. Certificates & secrets → New client secret → copy value (only shown once)
  4. Issuer URL: https://login.microsoftonline.com/<tenant-id>/v2.0
  1. Auth0 dashboard → Applications → Create application → Regular Web Applications
  2. Allowed callback URLs: https://<your-swarm>/api/v1/auth/oidc/callback
  3. Issuer URL: https://<your-tenant>.auth0.com/

2. Configure swarm#

Add to .env:

SWARM_OIDC_ENABLED=true
SWARM_OIDC_ISSUER=https://accounts.google.com
SWARM_OIDC_CLIENT_ID=<your-client-id>.apps.googleusercontent.com
SWARM_OIDC_CLIENT_SECRET=<your-client-secret>
SWARM_OIDC_REDIRECT_URI=https://<your-swarm>/api/v1/auth/oidc/callback
SWARM_OIDC_SCOPES=openid email profile
SWARM_OIDC_AUTO_PROVISION=true            # creates swarm users on first login
SWARM_OIDC_DEFAULT_ROLE=viewer            # new users land here

Restart the api container.

curl -X PUT http://localhost:8000/api/v1/auth/oidc/config \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "issuer": "https://accounts.google.com",
    "client_id": "...",
    "client_secret": "...",
    "redirect_uri": "https://<your-swarm>/api/v1/auth/oidc/callback",
    "scopes": ["openid", "email", "profile"],
    "auto_provision": true,
    "default_role": "viewer"
  }'

3. Test the flow#

  1. Open an incognito browser → https://<your-swarm>/
  2. Click Sign in with SSO
  3. Redirected to your IdP → authenticate
  4. Redirected back to swarm dashboard → logged in

Verify with:

swarm whoami
# {"email": "alice@yourorg.com", "role": "viewer", "provider": "oidc:google"}

4. Map IdP groups to swarm roles#

swarm has 3 built-in roles: viewer, operator, admin. Map IdP groups via policy:

# config/permission_policies_org.yaml
rules:
  - if:
      claim: groups
      contains: "swarm-admins"
    then_role: admin
  - if:
      claim: groups
      contains: "swarm-operators"
    then_role: operator
  - else:
      role: viewer

Restart to apply. Now users land with the right role based on their IdP group membership at login.

5. Enforce OIDC-only (disable local passwords)#

Once SSO is working:

swarm features set local_password_auth off

Local login via the seeded admin no longer works. All sign-ins must go through OIDC. Reversible in case of IdP outage (you'll need to exec into the API container and flip the flag via env var).

6. Per-IdP group claim#

Some IdPs emit groups differently:

IdP Claim key Notes
Google Workspace groups Requires admin to enable Directory API + grant groups.readonly scope
Okta groups Default; ensure app config includes groups in ID token
Azure AD groups Emits object IDs, not names by default — either configure "group display names" or use the object ID in the policy
Auth0 https://yourtenant/groups Use a Rule to add groups to the ID token

Debug: swarm auth oidc debug decodes the current user's ID token so you can see the claims.

Advanced#

Refresh tokens#

swarm caches the access token + refresh token. When the access token expires, a background refresh kicks in. If refresh fails (user deprovisioned at IdP), the next API call returns 401.

MFA#

swarm doesn't enforce MFA itself — it's inherited from your IdP. Configure MFA at the IdP and it applies automatically.

SAML#

SAML is not yet supported. If you need it, open an issue. We plan to add it after SCIM in a later release.

SCIM (user provisioning)#

Automated provisioning / deprovisioning via SCIM 2.0 is on the roadmap for v0.12. For now, auto-provision on first login + role-via-groups covers most teams.

Troubleshooting#

Redirect URI mismatch error

The URI registered at your IdP must match SWARM_OIDC_REDIRECT_URI exactly — including trailing slash, scheme (http vs https), and port.

401 after OIDC redirect

Check api logs for the OIDC callback — usually indicates clock skew (>30s between swarm and IdP) or a missing scope.

Groups claim missing from ID token

Depends on IdP config. For Google, Directory API + groups.readonly scope needed. For Azure AD, enable "groups claim" in app manifest.

Next#