#182
fix(auth): check token expiry before scopes in withMcpAuth
Summary
- Expired tokens that also lack a required scope now correctly return
401 invalid_tokeninstead of403 insufficient_scope - Moves the
expiresAtcheck above therequiredScopescheck inwithMcpAuthso 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)
Activity
4allenzhou101approved changes3mo ago
Hi @quuu — following up on this PR. It is still mergeable, all checks are passing, and @allenzhou101 approved the change. The fix and regression tests are ready. Could you please take a maintainer look when you have a chance? I’m happy to address any additional feedback.
@allenzhou101