Skip to content

fix(session): Reject non-user access tokens in session cookies - #573

Merged
gjtorikian merged 3 commits into
mainfrom
fix/session-user-access-token-claims
Nov 6, 2026
Merged

gjtorikian merged 3 commits into
mainfrom
fix/session-user-access-token-claims

Conversation

@m0tzy

@m0tzy m0tzy commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Session#authenticate (and SessionManager#authenticate, which delegates to it) verified the sealed access token's signature, expiry and issuer, but not that it was a user session access token. Other token types signed by the same environment key were accepted as a session.

After decode_jwt, it now returns INVALID_JWT unless the new private user_access_token?(decoded) check passes:

claims["sid"].is_a?(String) &&
  claims["auth_time"].is_a?(Numeric) &&
  [nil, "user"].include?(claims["sub_profile"]) &&   # absent is still accepted
  claims["sub_type"].nil?

This matches hasRequiredAccessTokenClaims in workos-node. sub_profile is optional on user access tokens, so a missing claim is still accepted. The check runs before the include_expired branch, so non-user tokens are also rejected there.

Tests: new cases seal tokens with sub_profile: ai_agent, sub_type: authkit, and no auth_time, and expect INVALID_JWT. There is also a positive case for sub_profile: user. The 3 rejection cases fail without the session.rb change. make_jwt now defaults auth_time, as real user access tokens include it.

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

Session#authenticate now requires the verified access token to carry
sid and auth_time, a sub_profile that is absent or user, and no
sub_type, so other token types signed by the same environment key do
not authenticate a session.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@m0tzy
m0tzy requested review from a team as code owners November 4, 2026 22:08
@m0tzy
m0tzy requested a review from tribble November 4, 2026 22:08
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

Original prompt from madison.packer

What's the fix here? https://linear.app/workos/issue/VULN-4839/lt-app26-10-user-vs-agent-jwt-type-confusion

@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: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Devin Review

🟢 Devin Review found nothing to fix · View findings

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@greptile-apps

greptile-apps Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no new actionable issues were found.

Summary

Session#authenticate now rejects non-user access tokens before returning session claims.

  • Session cookies only authenticate with user-session tokens.

Reviews (2) · Last reviewed commit: "test(session): Cover expired non-user to..." · Reviewed by Greptile

Comment thread test/workos/test_session.rb Resolved
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

@greptileai review

@gjtorikian

Copy link
Copy Markdown
Contributor

thank you!

@gjtorikian
gjtorikian merged commit 94be822 into main Nov 6, 2026
10 checks passed
@gjtorikian
gjtorikian deleted the fix/session-user-access-token-claims branch November 6, 2026 15:44
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.

2 participants