-
Notifications
You must be signed in to change notification settings - Fork 48
feat: guide - verifying jwts in cloudflare workers #611
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughA new MDX documentation page was added that explains how to verify JSON Web Tokens (JWTs) in Cloudflare Workers, covering prerequisites, Wrangler setup, JWKS handling, two verification approaches (cloudflare-worker-jwt and jose), sample code, local testing, and deployment steps. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Worker
participant JWKS as JWKS Endpoint
Note over Worker: Verification flow (two alternatives)
Client->>Worker: HTTP request with Authorization: Bearer <token>
Worker->>Worker: extract token from header
Worker->>JWKS: GET /.well-known/jwks.json
JWKS-->>Worker: JWKS (keys)
alt Use cloudflare-worker-jwt
Worker->>Worker: extract modulus & import key (WebCrypto)
Worker->>Worker: cloudflare-worker-jwt.verify(token, key)
else Use jose
Worker->>Worker: build JWK / import via crypto.subtle
Worker->>Worker: jose.verify(token, key)
end
alt verification succeeds
Worker-->>Client: 200 OK (authorized)
else verification fails
Worker-->>Client: 401 / 403 (error)
end
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying kinde-docs-preview with
|
| Latest commit: |
1e828b8
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e48ac4da.kinde-docs-preview.pages.dev |
| Branch Preview URL: | https://tamal-feat-verify-jwt-cloudf.kinde-docs-preview.pages.dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx (1)
119-146: Clarify the helper function's actual purpose and output.The function is documented as extracting "the public key" but only returns the modulus (the
nvalue). The exponent (e) is hardcoded as'AQAB'in both implementations. Either clarify in the documentation that this function extracts only the modulus, or rename it toextractJwksModulusto reflect its actual behavior.For example:
// Before export async function extractPublicKey(jwksUrl) { try { // Fetch the JWKS JSON from the URL const response = await fetch(jwksUrl); if (!response.ok) { throw new Error(`Failed to fetch JWKS: ${response.statusText}`); } const jwks = await response.json(); if (!jwks.keys || jwks.keys.length === 0) { throw new Error('No keys found in JWKS'); } // Extract the 'n' (modulus) from the first key const { n } = jwks.keys[0]; if (!n) { throw new Error("'n' key not found in the JWKS"); } return n; } catch (error) { console.error(`Error extracting modulus: ${error.message}`); throw error; } }Option A (recommended): Update the comment and function name:
-// This function extracts the public key from your JWKS URL. +// This function extracts the modulus (n value) from your JWKS URL for RSA public key construction. -export async function extractPublicKey(jwksUrl) { +export async function extractJwksModulus(jwksUrl) {Option B: Enhance to return both
nande:- return n; + return { n, e: jwks.keys[0].e || 'AQAB' };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx(1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.28.0)
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx
[high] 311-311: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
🔇 Additional comments (2)
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx (2)
308-312: Static analysis flag is a false positive; no action needed.Gitleaks flagged the curl command at line 311 due to the Authorization header. However, this is instructional documentation with a clearly marked placeholder token (
YOUR_JWT), not an actual secret. No changes are required. This is appropriate guidance for users testing their Worker locally.
1-44: Excellent documentation structure and coverage.The guide is well-organized with clear step-by-step instructions, prerequisites, two implementation approaches, testing guidance, and deployment steps. The introduction effectively explains the use case and limitations of Cloudflare Workers. Once the variable shadowing issues in the code examples are resolved (as noted in earlier comments), this will be a high-quality integration guide.
| ```jsx | ||
| import { verify } from '@tsndr/cloudflare-worker-jwt'; | ||
| import { extractPublicKey } from './helper'; | ||
|
|
||
| export default { | ||
| async fetch(request) { | ||
| const token = request.headers.get('Authorization')?.split(' ')[1]; | ||
| if (!token) { | ||
| return new Response('No token provided', { status: 401 }); | ||
| } | ||
|
|
||
| const jwksUrl = 'https://<your_kinde_account>.kinde.com/.well-known/jwks'; | ||
| const publicKey = await extractPublicKey(jwksUrl); | ||
|
|
||
| // Define the public key in JWK format | ||
| const jwk = { | ||
| kty: 'RSA', | ||
| e: 'AQAB', | ||
| n: publicKey, | ||
| alg: 'RS256', | ||
| use: 'sig', | ||
| }; | ||
|
|
||
| try { | ||
| // Import the public key | ||
| const publicKey = await crypto.subtle.importKey( | ||
| 'jwk', | ||
| jwk, | ||
| { | ||
| name: 'RSASSA-PKCS1-v1_5', | ||
| hash: { name: 'SHA-256' }, | ||
| }, | ||
| false, | ||
| ['verify'] | ||
| ); | ||
|
|
||
| const isValid = await verify(token, publicKey, { algorithm: 'RS256' }); | ||
|
|
||
| if (isValid) { | ||
| return new Response('Token is valid', { status: 200 }); | ||
| } else { | ||
| return new Response('Token is invalid', { status: 401 }); | ||
| } | ||
| } catch (error) { | ||
| return new Response(`Error verifying token: ${error.message}`, { status: 500 }); | ||
| } | ||
| }, | ||
| }; | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Resolve variable shadowing and make status codes consistent.
Line 188 reassigns publicKey from a string (the modulus) to a CryptoKey object. Use distinct variable names to improve clarity:
import { verify } from '@tsndr/cloudflare-worker-jwt';
import { extractPublicKey } from './helper';
export default {
async fetch(request) {
const token = request.headers.get('Authorization')?.split(' ')[1];
if (!token) {
return new Response('No token provided', { status: 401 });
}
const jwksUrl = 'https://<your_kinde_account>.kinde.com/.well-known/jwks';
- const publicKey = await extractPublicKey(jwksUrl);
+ const modulus = await extractPublicKey(jwksUrl);
// Define the public key in JWK format
const jwk = {
kty: 'RSA',
e: 'AQAB',
- n: publicKey,
+ n: modulus,
alg: 'RS256',
use: 'sig',
};
try {
// Import the public key
const publicKey = await crypto.subtle.importKey(
'jwk',
jwk,
{
name: 'RSASSA-PKCS1-v1_5',
hash: { name: 'SHA-256' },
},
false,
['verify']
);
const isValid = await verify(token, publicKey, { algorithm: 'RS256' });
if (isValid) {
return new Response('Token is valid', { status: 200 });
} else {
return new Response('Token is invalid', { status: 401 });
}
} catch (error) {
- return new Response(`Error verifying token: ${error.message}`, { status: 500 });
+ return new Response(`Error verifying token: ${error.message}`, { status: 401 });
}
},
};Also align the error status code with Option 2 (use 401 for verification failures instead of 500).
🤖 Prompt for AI Agents
In
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx
around lines 163 to 211, fix the variable shadowing and status code: rename the
string modulus variable (currently `publicKey`) to something distinct like
`publicKeyModulus` or `jwkN`, build the JWK using that name, and rename the
imported CryptoKey (currently also `publicKey`) to `publicCryptoKey` (or
`importedPublicKey`) to avoid reassignment and confusion; also change the catch
response status from 500 to 401 so verification failures return 401 and update
the error response message accordingly.
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx (1)
320-322: Minor: Add comma before "and" in the conclusion.The closing statement would benefit from a comma before "and" to improve readability:
-With your Cloudflare Worker deployed and JWT verification fully configured, you now have a scalable, secure solution... +With your Cloudflare Worker deployed, and JWT verification fully configured, you now have a scalable, secure solution...
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx(1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.29.0)
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx
[high] 297-297: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
🪛 LanguageTool
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx
[uncategorized] ~41-~41: Loose punctuation mark.
Context: ...fication: - cloudflare-worker-jwt: Lightweight and optimized for Cloudflar...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~42-~42: Loose punctuation mark.
Context: ...zed for Cloudflare Workers. - jose: More versatile, supporting a wide range...
(UNLIKELY_OPENING_PUNCTUATION)
[typographical] ~100-~100: It appears that a comma is missing.
Context: ...ant to use git for version control? No 2. Do you want to deploy your application? **...
(COMMA_BEFORE_QUESTION_WITH_MD)
[uncategorized] ~322-~322: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ...d! With your Cloudflare Worker deployed and JWT verification fully configured, you ...
(COMMA_COMPOUND_SENTENCE_2)
🔇 Additional comments (8)
src/content/docs/integrate/third-party-tools/verifying-jwts-cloudflare-workers.mdx (8)
1-44: ✓ Metadata and introduction are clear.The frontmatter is complete, and the introduction effectively explains the edge deployment benefits and introduces both verification libraries.
46-86: ✓ Prerequisites and Wrangler setup are well-structured.The installation steps are clear with visual confirmation. The browser screenshot aids user orientation.
88-150: ✓ Project setup and helper function are correct.The
extractPublicKeyhelper function properly validates the JWKS response and extracts the modulus. Error handling is appropriate.
154-211: ✓ Cloudflare Worker JWT example resolves past feedback.Variable shadowing is fixed:
modulus(line 174) correctly distinguishes the JWKS modulus from the importedpublicKeyCryptoKey (line 187). Error status code is consistent at 401 (line 206). The code flow is correct.
213-268: ✓ Jose example is consistent with first approach.Variable shadowing fix applied (line 233 uses
modulus, line 246 imports aspublicKey). Error handling returns 401 consistently (line 263). The payload destructuring fromjwtVerifyis correct.
273-301: ✓ Testing section provides clear, practical guidance.The local testing workflow is well-documented. The curl command (line 297) uses
YOUR_JWTas an explicit placeholder—this is appropriate for documentation and the security scanning flag is a false positive. The steps to retrieve the actual token from Kinde are clear.Confirm that users understand
YOUR_JWTis a placeholder and should not commit actual tokens to version control.
303-318: ✓ Deployment instructions are clear.The
wrangler deploycommand and confirmation screenshot provide good guidance for final deployment.
41-42: Minor documentation note: Grammar tool flagged markdown list items.Static analysis flagged loose punctuation on lines 41–42 (list items with colons) and a missing comma on line 100. These appear to be false positives given markdown documentation conventions. The formatting is appropriate for the target format.
Also applies to: 100-100
onderay
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved
Verifying JWTs in Cloudflare Workers
Learn how to securely verify JSON Web Tokens (JWTs) in Cloudflare Workers using the cloudflare-worker-jwt and jose libraries for fast, edge-based authentication.
Related issues & labels (optional)
Summary by CodeRabbit