Verifying JWTs in Cloudflare Workers
By Vlad Ionash —
Cloudflare Workers provide a serverless execution environment that enables developers to deploy applications globally at the edge, closer to users, for enhanced performance and reduced latency. This scalable, secure, and cost-effective platform simplifies the deployment process, eliminating the need for server management and significantly reducing operational costs.
There are currently caveats to operating Cloudflare Workers such as the inability to run most server side libraries and most packages containing dependencies that are not supported. More specifically, they only support Node.js packages that use webpack or another polyfill bundler since it is not Node.js. They will only run JavaScript code using the V8 engine on the edge network not in a Node.js runtime so any Node.js package that has Node.js specific dependencies like fs and net/http are not compatible.
We will have to find more easily integrated ways to replace some of our middlewares that do JWT signing. This where two specific libraries come into play, cloudflare-worker-jwt
and jose
.
The choice between cloudflare-worker-jwt
and jose
depends largely on your specific needs and environment. If you’re working exclusively within Cloudflare Workers and need a lightweight, optimized solution for JWT verification, cloudflare-worker-jwt
is likely the better choice. On the other hand, if you need a more versatile library that can handle a wide range of cryptographic operations beyond just JWTs, and across different environments, jose
would be more appropriate.
We will be showing how to do the JWT verification on both!
This library is designed to work within the Cloudflare Workers environment, which allows you to run JavaScript and WebAssembly code at the edge, closer to your users. Here’s how we set this up.
If you haven’t already, you’ll first need to set up a Cloudflare Worker. You can do this by visiting the Cloudflare Workers dashboard and creating a new worker. You’ll be provided with a script editor where you can write your code.
To use the cloudflare-worker-jwt
library in your Worker, you’ll typically use a tool like wrangler
that supports the use of npm packages in Workers. However, you can’t directly use npm packages in Cloudflare Workers without bundling them first. You might need to use a bundler like webpack or Rollup to include the library in your Worker script.
If you’re using Wrangler, you can add the library to your package.json
and bundle your project with it. Here’s how you can add it:
{
"dependencies": {
"cloudflare-worker-jwt": "^version"
}
}
Replace "^version"
with the latest version of the cloudflare-worker-jwt
library.
Once you have the library ready to use in your Worker, you can use it to verify JWTs:
import { verify } from 'cloudflare-worker-jwt';
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const token = request.headers.get('Authorization')?.split(' ')[1];
if (!token) {
return new Response('No token provided', { status: 401 });
}
const publicKey = 'YOUR_PUBLIC_KEY_HERE'; // Use your actual public key from the jwks endpoint
try {
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 });
}
}
It then uses the verify
function from the cloudflare-worker-jwt
library to check if the token is valid with the rs256
algorithm, using a public key that you must provide. You can grab your Kinde JWKS by navigating to this url: https://<YOUR_DOMAIN>.kinde.com/.well-known/jwks
.
You can also define the public key to point to the above URL for a more straightforward, adaptable way to manage the credentials.
The verify
function might have different parameters or options depending on the version of the library, so always check the latest documentation for the most accurate information. Error handling is crucial when dealing with authentication mechanisms. Make sure to appropriately handle any errors that might occur during the verification process.
Using the jose
library by panva
to verify a JWT in a Cloudflare Worker involves a slightly different approach compared to other libraries because jose
is designed with modern JavaScript features and standards in mind.
Ensure you have a Cloudflare Worker project set up. You can do this by visiting the Cloudflare Workers dashboard and creating a new worker. You’ll be provided with a script editor where you can write your code.
You would typically use a tool like wrangler
to manage your Cloudflare Worker projects. Since Cloudflare Workers do not natively support NPM packages, you will need to bundle your project along with its dependencies using a bundler like webpack or Rollup. Generally, you can install jose
by running npm install jose
or yarn add jose
in your project directory. Alternatively, use a bundler configured to target a WebWorker environment to include jose
in your Cloudflare Worker script.
With your environment set up and jose
added to your project, you can now write the code to verify JWTs in your Cloudflare Worker. Here’s an example:
import {jwtVerify} from "jose";
const handleRequest = async (request) => {
const token = request.headers.get("Authorization")?.split(" ")[1]; // Assuming the token is in the Authorization header
if (!token) {
return new Response("No token provided", {status: 401});
}
const publicKey = await crypto.subtle.importKey(
"jwk", // Assuming the key is in JWK format
{
kty: "RSA",
e: "AQAB",
n: "YOUR_PUBLIC_KEY_N_HERE",
alg: "RS256",
use: "sig"
},
{
name: "RSASSA-PKCS1-v1_5",
hash: {name: "SHA-256"}
},
false,
["verify"]
);
try {
const {payload} = await jwtVerify(token, publicKey);
// Optionally, check the payload for required claims
return new Response("Token is valid", {status: 200});
} catch (error) {
return new Response(`Token verification failed: ${error.message}`, {status: 401});
}
};
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
This example assumes your public key is in JWK format, like the one supplied by Kinde. You can grab your Kinde JWKS by navigating to this url:
https://<YOUR_DOMAIN>.kinde.com/.well-known/jwks
.
You can also define the public key to point to the above uri for a more straightforward, adaptable way to manage the credentials.
💡 After verifying the signature, you may want to inspect the JWT payload for specific claims (e.g., issuer, audience, expiration) to further validate the token’s authenticity and appropriateness for your application.
Whichever method you choose to deploy, you should now have everything you need to verify your JWTs on Cloudflare Workers!