Skip to content

fix(auth): check token expiry before scopes in withMcpAuth - #182

Open
anshusaurav wants to merge 1 commit into
vercel:mainfrom
anshusaurav:fix/auth-expiry-before-scope-181
Open

fix(auth): check token expiry before scopes in withMcpAuth#182
anshusaurav wants to merge 1 commit into
vercel:mainfrom
anshusaurav:fix/auth-expiry-before-scope-181

Conversation

@anshusaurav

Copy link
Copy Markdown

Summary

  • Expired tokens that also lack a required scope now correctly return 401 invalid_token instead of 403 insufficient_scope
  • Moves the expiresAt check above the requiredScopes check in withMcpAuth so expiry is always evaluated first, per RFC 6750 §3.1
  • Adds regression tests for expiry-vs-scope ordering, live+unscoped, live+scoped, expired-no-scopes-required, and missing-auth paths

Fixes #181

Why it matters

401 invalid_token tells an MCP client its token is no longer valid — the client should refresh or re-authenticate. 403 insufficient_scope tells the client it has the wrong permissions — the client will not refresh and may surface a misleading "insufficient permissions" error. When both conditions are true, RFC 6750 requires the expiry to win.

Test plan

  • New test: expired + missing scope → 401 invalid_token (was 403 before fix)
  • New test: live + missing scope → 403 insufficient_scope (unchanged)
  • New test: live + matching scope → 200 (unchanged)
  • New test: expired + no required scopes → 401 (unchanged)
  • New test: no auth + required → 401 (unchanged)
  • Full suite passes 29/29 (vitest run)

An expired token that also lacked a required scope was reported as
403 insufficient_scope instead of 401 invalid_token. Per RFC 6750
§3.1 an expired token is always invalid_token — this matters because
clients use the error code to decide whether to refresh the token or
surface a permissions error.

Move the expiresAt check above the requiredScopes check so expiry
is evaluated first. Add regression tests covering both orderings.

Fixes vercel#181
@quuu

quuu commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@allenzhou101

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

withMcpAuth returns 403 instead of 401 for expired tokens that also lack scopes

3 participants