fix(self-host): add hybrid JWT verification for edge functions docker template#42130
Conversation
|
Thanks for contributing to Supabase! ❤️ Our team will review your PR. A few tips for a smoother review process:
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@Athaxv is attempting to deploy a commit to the Supabase Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughDual-path JWT verification added: detects token algorithm and verifies ES256/RS256/EdDSA tokens via JWKS + issuer, or verifies HS256/unknown tokens via symmetric JWT_SECRET. Added stricter Authorization header validation, new helpers, expanded logging, and unified 401/error handling. Changes
Sequence DiagramsequenceDiagram
participant Client
participant AuthHandler as Auth Handler
participant JWTDetector as JWT Algorithm Detector
participant JWKS as JWKS Verifier
participant SymVerifier as Symmetric Verifier
Client->>AuthHandler: HTTP request with Authorization header
AuthHandler->>JWTDetector: extract token and decode header
JWTDetector-->>AuthHandler: algorithm (ES256/RS256/EdDSA/HS256/unknown)
alt Asymmetric (ES256/RS256/EdDSA)
AuthHandler->>JWKS: verify using SUPABASE_JWT_KEYS and issuer
JWKS-->>AuthHandler: verification success/failure
else Symmetric (HS256 or unknown)
AuthHandler->>SymVerifier: verify using JWT_SECRET
SymVerifier-->>AuthHandler: verification success/failure
end
AuthHandler-->>Client: respond 200 (success) or 401 (failure) with logs
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@docker/volumes/functions/main/index.ts`:
- Around line 33-56: Replace the manual base64url decoding in getJWTAlgorithm
with jose.decodeProtectedHeader: import decodeProtectedHeader from 'jose' (or
the correct named import) and call decodeProtectedHeader(jwt) inside
getJWTAlgorithm, then return header.alg || null; keep the try/catch to return
null on error so malformed tokens are handled the same way; update the function
signature and any tests to rely on decodeProtectedHeader instead of
atob/Uint8Array decoding.
|
@kallebysantos fyi |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docker/volumes/functions/main/index.ts (1)
36-45: Harden Authorization header parsing.Line 41–45 accepts
Bearerwith no token and ignores extra segments. This yields confusing failures downstream and accepts malformed headers.🔧 Proposed fix
function getAuthToken(req: Request) { const authHeader = req.headers.get('authorization') if (!authHeader) { throw new Error('Missing authorization header') } - const [bearer, token] = authHeader.split(' ') - if (bearer !== 'Bearer') { + const [bearer, token, ...rest] = authHeader.trim().split(/\s+/) + if (bearer !== 'Bearer' || !token || rest.length > 0) { throw new Error(`Auth header is not 'Bearer {token}'`) } return token }
🤖 Fix all issues with AI agents
In `@docker/volumes/functions/main/index.ts`:
- Around line 11-24: The JWKS/issuer URLs are built via string concatenation
which breaks when SUPABASE_URL has a trailing slash or path; normalize
SUPABASE_URL first (trim any trailing slash or construct a base URL object) and
then build the JWKS URL and issuer using URL resolution instead of simple
concatenation so jose.createRemoteJWKSet and SUPABASE_JWT_ISSUER always get
well-formed URLs; update the code around SUPABASE_JWT_KEYS, the
jose.createRemoteJWKSet call, and SUPABASE_JWT_ISSUER to use the normalized base
and URL constructor/resolution.
|
Hi @Athaxv and thanks so much for your contributions 💚 You're in the right path, its align with supabase/cli#4721 @aantti I do suggest to hold this one for a while, since its only affects the Self-Host environment and I think its not using the new api keys yet. -- I'm renaming it to better align with our internal threads. |
…r token algorithms Updated the JWT verification process to handle both HS256 (symmetric) and ES256/RS256 (asymmetric) algorithms. Introduced support for JWKS to verify newer tokens, ensuring compatibility and resolving issues with legacy tokens in local Docker environments.
0867141 to
96cf4b1
Compare
Description
Fixes issue supabase/cli#4754 where edge functions fail when verifying JWT tokens that use the ES256 algorithm. The error occurs because the verification function attempts to use a
Uint8Array(fromJWT_SECRET) where aCryptoKeyis required for ES256 algorithm verification.Solution
Implemented algorithm detection and dual verification paths:
Algorithm Detection: Added
getJWTAlgorithm()function to decode JWT header and detect the algorithm (HS256, ES256, RS256, EdDSA)JWKS Support: Added support for JWKS endpoint:
SUPABASE_JWT_KEYS: Remote JWKS set for fetching public keysSUPABASE_JWT_ISSUER: Issuer validation for asymmetric tokensDual Verification Paths: Refactored
verifyJWT()to route verification based on algorithm:JWT_SECRET(Uint8Array) for symmetric verificationBackward Compatibility: Maintains full backward compatibility with existing HS256 token verification
Changes
SUPABASE_URLenvironment variable readingSUPABASE_JWT_KEYSandSUPABASE_JWT_ISSUERconstants for JWKS supportgetJWTAlgorithm()function to detect algorithm from JWT headerverifyJWT()function with algorithm-based routingI have read the CONTRIBUTING.md file.
Summary by CodeRabbit
New Features
Bug Fixes & Improvements
✏️ Tip: You can customize this high-level summary in your review settings.