Skip to content

feat: Add optional issuer option for session token validation - #1694

Open
m0tzy wants to merge 2 commits into
mainfrom
devin/1788636590-optional-issuer
Open

feat: Add optional issuer option for session token validation#1694
m0tzy wants to merge 2 commits into
mainfrom
devin/1788636590-optional-issuer

Conversation

@m0tzy

@m0tzy m0tzy commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Description

Adds an opt-in iss claim check when verifying session access tokens (authenticateWithSessionCookie and loadSealedSession(...).authenticate()). A new WorkOSOptions.issuer?: string | string[] is threaded through UserManagement.issuer to both isValidJwt implementations and passed straight to jose.jwtVerify, which natively accepts a single issuer or a list:

await jwtVerify(accessToken, jwks, issuer ? { issuer } : undefined);

When issuer is not set, behavior is unchanged (no iss validation). Opt-in rather than defaulted because the API does not mint a single issuer shape — it varies by environment (https://api.workos.com for legacy environments, https://api.workos.com/user_management/<clientId> for environments created since mid-2025, custom auth domains, and flag-gated path variants). No env var is added here; the core SDK only reads WORKOS_API_KEY/WORKOS_CLIENT_ID from the environment and this option is passed programmatically like the rest of WorkOSOptions.

All edits are within @oagen-ignore blocks / ignore-marked files. Companion PRs: workos/authkit-nextjs#476, workos/authkit-remix#90, workos/authkit-react-router#85.

Documentation

Does this require changes to the WorkOS Docs? E.g. the API Reference or code snippets need updates.

[ ] Yes

README updated in this PR; no docs-site change required.

Link to Devin session: https://app.devin.ai/sessions/0ee38e859a9849658a7cdb2d215d89a6
Open in Devin Desktop: https://app.devin.ai/desktop/session/0ee38e859a9849658a7cdb2d215d89a6?variant=devin
Requested by: @m0tzy

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@m0tzy
m0tzy requested review from a team as code owners September 5, 2026 19:36
@m0tzy
m0tzy requested a review from dandorman September 5, 2026 19:36
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

Original prompt from madison.packer

can we patch this SDK so that the issuer can be either by default (if not passed) or passed a specific issuer?

const issuer = opts.issuer ?? https://${getConfig('apiHostname')}

workos/authkit-react-router#83

@devin-ai-integration devin-ai-integration Bot changed the title Add optional issuer option for session token validation feat: Add optional issuer option for session token validation Sep 5, 2026

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Devin Review

Comment thread src/user-management/user-management.ts Outdated
@greptile-apps

greptile-apps Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds optional issuer validation for session access tokens.

  • Adds WorkOSOptions.issuer with support for one or multiple allowed issuers.
  • Passes the configured issuer to JOSE verification in both session-cookie authentication paths.
  • Preserves existing behavior when no issuer is configured.
  • Adds documentation and coverage for option forwarding, environment-derived client IDs, and issuer mismatch error mapping.

Confidence Score: 4/5

The PR is not yet safe to merge because an explicitly configured empty-string issuer still disables issuer validation in both authentication paths.

The previous issuer-validation finding remains unresolved: both session.ts and user-management.ts still use truthiness checks, so issuer: '' passes undefined to JOSE and silently skips the configured issuer check. The previous test-coverage finding is fixed by the new claim-validation error-mapping tests.

Files Needing Attention: src/user-management/session.ts, src/user-management/user-management.ts

Important Files Changed

Filename Overview
src/common/interfaces/workos-options.interface.ts Adds the optional public issuer configuration supporting a string or list of strings.
src/user-management/session.ts Threads issuer validation into sealed-session authentication, but an empty string still disables the configured check.
src/user-management/user-management.ts Propagates the resolved client ID and issuer into direct session-cookie verification, with the same empty-string fail-open behavior.
src/user-management/session.spec.ts Covers issuer forwarding and maps simulated JOSE claim-validation failures to invalid_jwt.
src/user-management/user-management.spec.ts Covers issuer forwarding, environment-derived client IDs, and issuer mismatch error mapping.
README.md Documents opt-in access-token issuer validation and support for multiple issuers.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    App[Application configuration] --> WorkOS[WorkOS client]
    WorkOS --> UM[UserManagement]
    UM --> A[authenticateWithSessionCookie]
    UM --> S[CookieSession.authenticate]
    A --> Verify[JOSE jwtVerify]
    S --> Verify
    Verify -->|issuer matches or is not configured| Auth[Authenticated session]
    Verify -->|issuer mismatch| Invalid[invalid_jwt]
Loading

Reviews (2): Last reviewed commit: "Use resolved clientId in UserManagement ..." | Re-trigger Greptile

Comment thread src/user-management/session.ts
Comment thread src/user-management/session.spec.ts
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant