ITADN

Expose session AMR / MFA-this-session signal in access JWT or webhook

#655Openbrett 创建于 2026-05-11
B
brettcommented
## Use case We're a B2B SaaS running AuthKit-managed SSO via `workos-python` 5.x. Our ISMS (SOC 2 / ISO 27001 controls) requires us to enforce MFA *for the current session* at the API request boundary — not "is the user MFA-enrolled". For a privileged action we need to answer "did this user MFA when this session was established?", and 403 if not. ## What's missing We can't answer that question with WorkOS today: - **JWT templates** [explicitly cannot expose `session.amr` or MFA info](https://workos.com/docs/authkit/jwt-templates) (template surface is `user` / `organization` / `organization_membership` only). - **Standard access JWT** has no `amr` or `acr` claim. Confirmed in our dev environment — the JWT contains: ``` client_id, email, email_verified, exp, iat, iss, jti, name, org_id, permissions, role, roles, sid, sub ``` - **`load_sealed_session().authenticate()` / `authenticate_with_session_cookie`** decode the JWT internally but [only surface named claims](https://github.com/workos/workos-python/blob/master/workos/session.py) (`sid`, `org_id`, `role`, `roles`, `permissions`, `entitlements`, `feature_flags`). Anything else is dropped. - **`authentication.mfa_succeeded` webhook** has `user_id, email, ip_address, user_agent` but **no `session_id`**, so correlation with `session.created` is heuristic (user_id + close timestamp + IP/UA match). Not cryptographically tied to a session; insufficient for audit evidence. - **`list_authentication_factors`** answers enrollment, not session-MFA. A user with TOTP enrolled who logged in password-only would register as "MFA'd" under this signal. - **AuthKit Actions** are [Allow/Deny only](https://workos.com/docs/authkit/actions); can't mint custom JWT claims or attach session attributes. - **Organization Authentication Policies** can require MFA at the org level, but the policy is toggleable, doesn't appear in the token, and gives no per-request verification. ## What we'd want (any one of these) In priority order: 1. **`amr` claim in the access JWT** (standard OIDC, e.g. `["mfa"]` or `["pwd", "totp"]`). Would let the API verify session-MFA without an extra round-trip. Cleanest answer. 2. **`session_id` on the `authentication.mfa_succeeded` webhook payload.** Lets us build a `(session_id → mfa_verified_at)` table from webhook events and tie session establishment to MFA cryptographically. Less convenient than (1) but workable. 3. **Custom-claim minting in AuthKit Actions.** Lets us write a one-line Action that copies AMR from session context to a JWT claim ourselves. Most flexible; works for adjacent use cases (custom roles, feature flags, etc.). ## Why filing here Not strictly an SDK issue — the underlying API change is what unblocks this. But since `workos-python` is the SDK we use, and the SDK's `AuthenticateWithSessionCookieSuccessResponse` would need to surface `amr` even if the API shipped it, recording the request here. If there's a better place to route this (internal tracker, support ticket, public roadmap), happy to mirror. ## Related - Cross-link: same ask filed on `workos/authkit-nextjs` for the consumer-side SDK helper. (will paste link after filing)
1 条评论