Conversation
- Extract ParseJWT for type-agnostic signature verification and claims extraction - Enforce strict type checking in ValidateToken and ValidateRefreshToken - Replace error-parameter pattern with base errors and mapRefreshError translator - Move ScopeSet to util package and remove duplicate parseScopeSet - Add token category constants and remove unused error sentinels - Fix HTTPTokenProvider.GenerateClientCredentialsToken expiration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add check for absolute URLs that have a scheme but no host (e.g. "http:") - These should be rejected as unsafe redirects Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR refactors JWT validation logic in the token package to enforce strict token type checks, extract a ParseJWT method for type-agnostic parsing, and consolidate the ScopeSet utility to internal/util/string.go. It also fixes a bug where HTTPTokenProvider.GenerateClientCredentialsToken was incorrectly using the standard JWT expiration instead of the dedicated client-credentials expiration.
Changes:
- Adds
TokenCategoryAccess/TokenCategoryRefreshconstants and removes dead error sentinels (ErrTokenValidation,ErrTokenReused);ValidateToken/ValidateRefreshTokennow enforce stricttypeclaim checks, and aParseJWTmethod is exposed for type-agnostic parsing (e.g., ID tokens in tests). - Consolidates the
ScopeSethelper fromtoken/idtoken.goandhandlers/oidc.gointoutil/string.go, eliminating theservices → tokenimport dependency inauthorization.go. - Fixes
HTTPTokenProvider.GenerateClientCredentialsTokento useClientCredentialsTokenExpirationinstead of delegating toGenerateToken(which usedJWTExpiration).
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
internal/util/string.go |
Adds ScopeSet as a shared utility |
internal/util/string_test.go |
Table-driven tests for ScopeSet including edge cases |
internal/token/types.go |
Adds TokenCategoryAccess and TokenCategoryRefresh constants |
internal/token/errors.go |
Removes unused ErrTokenValidation and ErrTokenReused sentinels |
internal/token/idtoken.go |
Removes ScopeSet (now in util) and its strings import |
internal/token/local.go |
Extracts ParseJWT, keyFunc; adds mapRefreshError; ValidateToken/ValidateRefreshToken delegate to ParseJWT with strict type checks |
internal/token/http_api.go |
Removes invalidErr/expiredErr params from callValidateAPI; fixes GenerateClientCredentialsToken to use correct expiration; ValidateRefreshToken uses mapRefreshError |
internal/token/local_test.go |
New tests for type-checking in ValidateToken/ValidateRefreshToken, mapRefreshError coverage, and parseIDTokenClaims helper using ParseJWT |
internal/services/token.go |
Switches from token.ScopeSet to util.ScopeSet |
internal/services/token_test.go |
Updates ID token claim tests to use ParseJWT; updates error assertion |
internal/services/authorization.go |
Uses util.ScopeSet instead of inline map-building loop |
internal/handlers/oidc.go |
Uses util.ScopeSet; removes local parseScopeSet |
internal/handlers/oidc_test.go |
Removes tests for parseScopeSet (now covered by util/string_test.go) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
- Verify HTTPTokenProvider.GenerateClientCredentialsToken sends expires_in from ClientCredentialsTokenExpiration, not JWTExpiration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
ParseJWTas an exported method for type-agnostic JWT signature verification and claims extraction, enabling callers (e.g. ID token tests) to parse tokens without type constraintsValidateTokenrequirestype == "access",ValidateRefreshTokenrequirestype == "refresh", each returning precise error messagesinvalidErr/expiredErrpassed into shared helpers) with base errors +mapRefreshErrortranslator in bothLocalTokenProviderandHTTPTokenProviderScopeSetfromtoken/idtoken.gotoutil/string.go, remove duplicateparseScopeSetfrom handlers, and eliminateservices → tokenimport dependency inauthorization.goTokenCategoryAccess/TokenCategoryRefreshconstants, remove deadErrTokenValidation/ErrTokenReusedsentinelsHTTPTokenProvider.GenerateClientCredentialsTokento useClientCredentialsTokenExpirationinstead of standard JWT expirationTest plan
internal/token,internal/handlers,internal/services)ValidateTokenrejecting refresh and ID tokens with specific error messagesValidateRefreshTokenrejecting access tokens and returning refresh-specific errorsmapRefreshErrorcovering direct, wrapped, and unrelated errorsTestScopeSetinutil/string_test.gowith edge cases (empty, single, multiple, extra whitespace)🤖 Generated with Claude Code