Skip to content

fix(self-host): add hybrid JWT verification for edge functions docker template#42130

Merged
aantti merged 5 commits intosupabase:masterfrom
Athaxv:fix/createClient-faiure-local-edge-function-using-JWT-keys
Mar 16, 2026
Merged

fix(self-host): add hybrid JWT verification for edge functions docker template#42130
aantti merged 5 commits intosupabase:masterfrom
Athaxv:fix/createClient-faiure-local-edge-function-using-JWT-keys

Conversation

@Athaxv
Copy link
Copy Markdown
Contributor

@Athaxv Athaxv commented Jan 24, 2026

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 (from JWT_SECRET) where a CryptoKey is required for ES256 algorithm verification.

Solution

Implemented algorithm detection and dual verification paths:

  1. Algorithm Detection: Added getJWTAlgorithm() function to decode JWT header and detect the algorithm (HS256, ES256, RS256, EdDSA)

  2. JWKS Support: Added support for JWKS endpoint:

    • SUPABASE_JWT_KEYS: Remote JWKS set for fetching public keys
    • SUPABASE_JWT_ISSUER: Issuer validation for asymmetric tokens
  3. Dual Verification Paths: Refactored verifyJWT() to route verification based on algorithm:

    • HS256 tokens → Uses JWT_SECRET (Uint8Array) for symmetric verification
    • ES256/RS256/EdDSA tokens → Uses JWKS endpoint (CryptoKey) for asymmetric verification
  4. Backward Compatibility: Maintains full backward compatibility with existing HS256 token verification

Changes

  • Added SUPABASE_URL environment variable reading
  • Added SUPABASE_JWT_KEYS and SUPABASE_JWT_ISSUER constants for JWKS support
  • Added getJWTAlgorithm() function to detect algorithm from JWT header
  • Refactored verifyJWT() function with algorithm-based routing
  • Enhanced error handling for missing environment variables and invalid tokens

I have read the CONTRIBUTING.md file.

Summary by CodeRabbit

  • New Features

    • Authentication now supports multiple JWT verification methods (asymmetric and symmetric) with algorithm detection and remote key retrieval.
  • Bug Fixes & Improvements

    • Stricter Authorization header parsing with unified 401 handling for malformed or missing tokens.
    • Expanded logging and clearer error paths for authentication and verification failures.

✏️ Tip: You can customize this high-level summary in your review settings.

@Athaxv Athaxv requested review from a team as code owners January 24, 2026 16:33
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for contributing to Supabase! ❤️ Our team will review your PR.

A few tips for a smoother review process:

  • If you have a local version of the repo, run pnpm run format to make sure formatting checks pass.
  • Once we've reviewed your PR, please don't trivially merge master (don't click Update branch if there are no merge conflicts to be fixed). This invalidates any pre-merge checks we've run.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
design-system Ready Ready Preview, Comment Mar 16, 2026 3:54pm
docs Ready Ready Preview, Comment, Open in v0 Mar 16, 2026 3:54pm
learn Ready Ready Preview, Comment Mar 16, 2026 3:54pm
studio-self-hosted Ready Ready Preview, Comment Mar 16, 2026 3:54pm
studio-staging Ready Ready Preview, Comment Mar 16, 2026 3:54pm
ui-library Ready Ready Preview, Comment Mar 16, 2026 3:54pm
zone-www-dot-com Ready Ready Preview, Comment, Open in v0 Mar 16, 2026 3:54pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
cms Ignored Ignored Mar 16, 2026 3:54pm
studio Ignored Ignored Mar 16, 2026 3:54pm

Request Review

@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 24, 2026

@Athaxv is attempting to deploy a commit to the Supabase Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 24, 2026

Walkthrough

Dual-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

Cohort / File(s) Summary
JWT verification & helpers
docker/volumes/functions/main/index.ts
Added getJWTAlgorithm() and verifyJWT(); tightened getAuthToken() header parsing; implemented branching verification: JWKS-based asymmetric verification (ES256/RS256/EdDSA) requiring SUPABASE_JWT_KEYS/SUPABASE_JWT_ISSUER, and symmetric HS256 verification requiring JWT_SECRET. Unified error/401 paths and expanded logging (+104/-5).

Sequence Diagram

sequenceDiagram
    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
Loading

Possibly related PRs

Suggested reviewers

  • laktek
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description covers all required template sections including confirmation of reading CONTRIBUTING.md, change type, current behavior (issue reference), new behavior (solution with detailed sections), and additional context.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title accurately captures the main change: adding hybrid JWT verification (supporting both symmetric HS256 and asymmetric ES256/RS256 tokens) for the edge functions docker template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread docker/volumes/functions/main/index.ts Outdated
@aantti
Copy link
Copy Markdown
Contributor

aantti commented Jan 24, 2026

@kallebysantos fyi

@aantti aantti self-assigned this Jan 24, 2026
@aantti aantti added edge functions self-hosted Related to self-hosted Supabase labels Jan 24, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Bearer with 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.

Comment thread docker/volumes/functions/main/index.ts Outdated
@kallebysantos
Copy link
Copy Markdown
Member

kallebysantos commented Feb 14, 2026

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.

@kallebysantos kallebysantos changed the title fix: ES256 JWT token verification in edge function runtime (#42072) fix(self-host): add hybrid JWT verification for edge functions docker template Feb 14, 2026
Comment thread docker/volumes/functions/main/index.ts Outdated
Athaxv and others added 4 commits March 16, 2026 12:07
…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.
@kallebysantos kallebysantos force-pushed the fix/createClient-faiure-local-edge-function-using-JWT-keys branch from 0867141 to 96cf4b1 Compare March 16, 2026 15:41
@aantti aantti merged commit edf51df into supabase:master Mar 16, 2026
29 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

edge functions self-hosted Related to self-hosted Supabase

Projects

Development

Successfully merging this pull request may close these issues.

4 participants