Skip to content

feat(okta): group-to-role mapping, user auto-provisioning and userinfo enrichment#6574

Open
an0nym21 wants to merge 7 commits into
keephq:mainfrom
an0nym21:feat/okta-group-role-mapping
Open

feat(okta): group-to-role mapping, user auto-provisioning and userinfo enrichment#6574
an0nym21 wants to merge 7 commits into
keephq:mainfrom
an0nym21:feat/okta-group-role-mapping

Conversation

@an0nym21

@an0nym21 an0nym21 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add `OKTA_ADMIN_GROUPS`, `OKTA_NOC_GROUPS`, `OKTA_WEBHOOK_GROUPS` env vars to map Okta group membership to Keep roles
  • Use the Okta ID token (instead of access token) as the bearer credential sent to the Keep API, so that app-level group claims are visible to the backend
  • Request the `groups` scope during OIDC authorization to trigger Okta's app-level group claim inclusion in the ID token
  • Accept both `OKTA_CLIENT_ID` and `OKTA_AUDIENCE` as valid token audiences (ID tokens use the client ID as audience)
  • Auto-provision users in Keep's DB on first login; update role and last-login on subsequent logins
  • Fix `OktaIdentityManager.get_users()` which previously returned an empty list
  • Add `OKTA_USERINFO_URL` env var to override the userinfo endpoint URL
  • Document new env vars in `docs/deployment/authentication/okta-auth.mdx`

How it works

Okta app-level Group Claims (configured under Sign On → OpenID Connect ID Token) are embedded in the ID token only — they do not appear in the access token or the `/v1/userinfo` response.

This PR switches the Okta auth flow to forward the ID token to the Keep API (matching the approach already used for Auth0 and OneLogin). The backend verifies the ID token signature via JWKS, reads the `groups` claim directly from the JWT payload, and resolves the highest-priority matching Keep role.

Role priority: `admin` > `noc` > `webhook`

Configuration example

OKTA_ADMIN_GROUPS=Keep_Admin
OKTA_NOC_GROUPS=Keep_User
OKTA_WEBHOOK_GROUPS=Keep_Webhook

Note: the Okta app must have a Group Claim configured under Sign On → OpenID Connect ID Token with filter e.g. "Starts with `Keep_`".

Fixes #6573

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. Documentation Improvements or additions to documentation Feature A new feature labels Jun 11, 2026
@an0nym21 an0nym21 force-pushed the feat/okta-group-role-mapping branch from 1abe3be to e01b9bf Compare June 12, 2026 07:22
an0nym21 added 6 commits June 22, 2026 11:01
Okta group memberships included in the JWT `groups` claim can now be
mapped to Keep roles through environment variables:

  OKTA_ADMIN_GROUPS=keep-admins,platform-team
  OKTA_NOC_GROUPS=keep-noc,ops-team
  OKTA_WEBHOOK_GROUPS=keep-webhooks

When multiple groups match, the highest-privilege role wins
(admin > noc > webhook). If no mapping is configured or no group
matches, the previous fallback chain is preserved:
`keep_role` claim → `role` claim → first group value → "noc" default.

This mirrors the existing KEEP_OAUTH2_PROXY_*_ROLES mechanism and
removes the need to configure custom claims on the Okta authorization
server for group-based setups.

Documentation updated accordingly.
Access tokens from Okta do not include group claims configured at the
app level. Call /v1/userinfo on each request to retrieve groups, name,
and email from the profile — falling back to JWT claims if absent.

Adds OKTA_USERINFO_URL env var to override the default derived URL.
…sioning

Also fix role fallback: unmapped groups should resolve to DEFAULT_ROLE_NAME
when group mappings are configured, not use the raw group name as a role.
Okta app-level group claims (configured via Sign On → Group claim filter)
are embedded in the ID token only — they do not appear in the access token
or the /v1/userinfo response.  Passing the ID token to the Keep API allows
the backend to read the `groups` claim directly from the JWT payload and
resolve the correct role via OKTA_*_GROUPS mappings.

Changes:
- auth.config.ts: use account.id_token instead of account.access_token for
  Okta; refresh flow also returns the new id_token; remove non-standard
  `groups` scope from the authorization request
- okta_authverifier.py: skip userinfo call when `groups` is already present
  in the JWT (ID tokens cannot be used as bearer for the userinfo endpoint);
  downgrade userinfo log to debug to reduce PII exposure
@an0nym21 an0nym21 force-pushed the feat/okta-group-role-mapping branch from 5537639 to ad10d67 Compare June 22, 2026 09:02
@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 30.49%. Comparing base (62235d8) to head (ad10d67).
⚠️ Report is 3 commits behind head on main.

❗ There is a different number of reports uploaded between BASE (62235d8) and HEAD (ad10d67). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (62235d8) HEAD (ad10d67)
2 1
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #6574       +/-   ##
===========================================
- Coverage   46.28%   30.49%   -15.79%     
===========================================
  Files         177      101       -76     
  Lines       18617    11735     -6882     
===========================================
- Hits         8616     3579     -5037     
+ Misses      10001     8156     -1845     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@an0nym21

Copy link
Copy Markdown
Contributor Author

Hi 👋 — I've updated the PR description to accurately reflect the final implementation (the key insight was that Okta app-level group claims are only available in the ID token, not the access token or userinfo endpoint).

Could someone take a look and let me know if anything is missing before this can be merged? Specifically:

  • Is the approach of forwarding the ID token to the API acceptable? (Auth0 and OneLogin already do this in the codebase)
  • Any concerns about the audience verification change (accepting both OKTA_CLIENT_ID and OKTA_AUDIENCE)?
  • Is the documentation in okta-auth.mdx sufficient?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation Improvements or additions to documentation Feature A new feature size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Okta group-to-role mapping and user auto-provisioning

1 participant