You may only deploy this edge function using CDN-as-Code due to Node.js dependencies. It will not work when deployed through the Edgio Console.
This example uses Edge Functions to validate a JSON Web Token (JWT) sent by a client. Handling this validation at the edge can help to offload the work from the origin server, and offer a more secure and efficient way to verify the token. Additionally, you can extend this edge function to check whether the client is authorized to access a protected resource or to verify the client’s identity.
Router Configuration
In the Edgio router, you can use the
edge_function
feature to specify the path to the edge function that will handle the JWT validation.JavaScriptroutes.js
1import {Router, edgioRoutes} from '@edgio/core';23export default new Router().use(edgioRoutes).post('/jwt', {4 edge_function: './edge-functions/validate.js',5});
Edge Function
This edge function uses the jsrsasign libary to validate a JWT signed with a HS256, HS384, or HS512 algorithm. It expects to receive a
POST
request with the following JSON payload:-
token: Required. This parameter must be set to the JWT that will be validated.
-
pubKey: By default, the JWT will be decoded using a default signing key (i.e.,
your-256-bit-secret
) defined within theJWT_SECRET
environment variable. However, you may decode it using a custom signing key by defining apubKey
parameter.This example allows you to pass a signing key to make it easier to test JWT validation through this edge function. However, signing keys should be kept secret. For example, a client should not pass a signing key within the request payload.
Upon completion, this edge function will report the result in the response.
Sample curl request:
Bash
1curl -X POST -d '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}' https://edgio-community-examples-v7-ef-jwt-validation-live.glb.edgio.link/jwt
Sample response:
{"valid":true,"alg":"HS256","payload":{"sub":"1234567890","name":"John Doe","iat":1516239022}}
Alternatively, you can validate JWTs by submitting the form on the following web page:
Code
This edge function’s code:
JavaScriptedge-functions/validate.js
1import { KJUR, KEYUTIL } from 'jsrsasign'2import { Buffer } from 'buffer'34// Set up some polyfills to allow this code to run locally and when deployed:5global.process = global.process || { env: {} }6const fromBase64 = (str) => Buffer.from(str, 'base64').toString()78export async function handleHttpRequest(request, context) {9 Object.assign(process.env, context.environmentVars)1011 // Extract the token and any other objects from the request.12 const { token, ...other } = await request.json()1314 // Split out the header and payload from the cleartext token and determine the right algorithm to use.15 const [header, payload] = token.split('.')16 const { alg } = JSON.parse(fromBase64(header))1718 let validationComponent = null19 let valid = false20 const resp = { valid }2122 try {23 // For HSxxx algorithms, the validation requires a plaintext secret key.24 // For RSxxx, ESxxx, and PSxxx algorithms, a public key is required instead.25 // The public key is expected to be part of the request payload and be named pubKey;26 // the secret key SHOULD NOT be part of the payload.27 // Note that for demo purposes (being able to set an arbitrary signing key) this28 // version of the EF will use the secret from `pubKey` if it exists.29 if (/^HS/i.test(alg)) {30 if ('pubKey' in other) {31 validationComponent = other.pubKey32 } else {33 validationComponent = process.env.JWT_SECRET34 }35 } else if (/^[REP]S/i.test(alg)) {36 validationComponent = KEYUTIL.getKey(other.pubKey)37 } else {38 return new Response('Invalid JWT alg specified.', { status: 401 })39 }4041 valid = KJUR.jws.JWS.verifyJWT(token, validationComponent, { alg: [alg] })42 if (valid === true) {43 // Only parse the payload if the signature is valid.44 const decodedPayload = JSON.parse(fromBase64(payload))45 Object.assign(resp, { valid, alg, payload: decodedPayload })46 }47 } catch (e) {48 // Handle exceptions here.49 }5051 return new Response(JSON.stringify(resp), {52 status: valid ? 200 : 40153 })54}