Skip to content

Commit ff95cc7

Browse files
authored
Merge pull request #154 from edgio-docs/v7-ef-jwt-validation
initial commit of ef-jwt-validation example project
2 parents 4d0ab48 + 83e9651 commit ff95cc7

File tree

11 files changed

+11056
-0
lines changed

11 files changed

+11056
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
**NOTICE TO CONTRIBUTORS**
2+
3+
This repository is not actively monitored and any pull requests made to this repository will be closed/ignored.
4+
5+
Please submit the pull request to [edgio-docs/edgio-examples](https://github.com/edgio-docs/edgio-examples) instead.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Deploy to Edgio
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
7+
jobs:
8+
deploy-to-edgio:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v3
12+
- uses: actions/setup-node@v3
13+
with:
14+
node-version: 18
15+
- run: if [ -f yarn.lock ]; then yarn install; else npm ci; fi
16+
- run: if [ -f yarn.lock ]; then yarn edgio:deploy -- --token=$EDGIO_DEPLOY_TOKEN; else npm run edgio:deploy -- --token=$EDGIO_DEPLOY_TOKEN; fi
17+
env:
18+
EDGIO_DEPLOY_TOKEN: ${{secrets.EDGIO_DEPLOY_TOKEN}}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# JWT Verification using Edge Functions
2+
3+
This repository provides sample code for verifying JSON Web Tokens (JWT) using Edge Functions. The response varies according to whether it is able to verify the JWT.
4+
- **Valid JWT:** Returns the decoded JWT.
5+
- **Invalid JWT:** Returns a `401 Unauthorized` response.
6+
7+
Try it at:
8+
9+
https://edgio-community-examples-v7-ef-jwt-validation-live.glb.edgio.link/jwt
10+
11+
## Prerequisites
12+
13+
This JavaScript project requires:
14+
15+
- An Edgio account.
16+
- Edge Functions activation. [Learn more about activation.](https://docs.edg.io/guides/v7/edge-functions)
17+
- Node.js v18 or higher
18+
- A UNIX-like system (Linux or macOS).
19+
20+
## Setup and Installation
21+
22+
1. Ensure you meet the prerequisites.
23+
2. Clone the repository to your local machine.
24+
3. Run `npm install` in the repository directory.
25+
26+
## Getting Started
27+
28+
After setting up the project, run `npm run edgio:dev` to start a local development server to test.
29+
30+
To deploy the project to Edgio, use the command `npm run edgio:deploy`. Deploying to Edgio requires you to be
31+
logged into Edgio CLI which can be done via `npm run edgio login` and the following the instructions.
32+
33+
## Known Issues and Limitations
34+
35+
Edge functions:
36+
37+
- Must use JavaScript code.
38+
- May only submit fetch requests to origins defined within your property configuration
39+
file (`edgio.config.js`).
40+
41+
[View additional limitations.](https://docs.edg.io/applications/edge_functions#limitations)
42+
43+
Validating tokens signed with RSxxx, ESxxx, or PSxxx algorithms generally takes more processing power than is currently available for Edge Functions. [Contact Edgio support](https://edg.io/contact-support/) to adjust the CPU and memory limits for your environment if you plan on validating these algorithms.
44+
45+
ESxxx algorithms use a very slow elliptical curve algorithm and may take longer than is allowed to validate, even with increased limits.
46+
47+
## Support
48+
49+
If you have any queries or face issues with this project, [contact
50+
us](https://edg.io/contact-support/).
51+
52+
## License
53+
54+
[Creative Commons Attribution 4.0 International Public License](LICENSE-CONTENT) for the documentation.
55+
56+
[MIT License](LICENSE-CODE) for the code.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { KJUR, KEYUTIL } from 'jsrsasign'
2+
import { Buffer } from 'buffer'
3+
4+
// Set up some polyfills to allow this code to run locally and when deployed:
5+
global.process = global.process || { env: {} }
6+
const fromBase64 = (str) => Buffer.from(str, 'base64').toString()
7+
8+
export async function handleHttpRequest(request, context) {
9+
Object.assign(process.env, context.environmentVars)
10+
11+
// Extract the toke and any other objects from the request.
12+
const { token, ...other } = await request.json()
13+
14+
// 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))
17+
18+
let validationComponent = null
19+
let valid = false
20+
const resp = { valid }
21+
22+
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) this
28+
// 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.pubKey
32+
} else {
33+
validationComponent = process.env.JWT_SECRET
34+
}
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+
}
40+
41+
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+
}
50+
51+
return new Response(JSON.stringify(resp), {
52+
status: valid ? 200 : 401
53+
})
54+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// This file was automatically added by edgio init.
2+
// You should commit this file to source control.
3+
// Learn more about this file at https://docs.edg.io/guides/edgio_config
4+
module.exports = {
5+
connector: '@edgio/express',
6+
7+
// The name of the site in Edgio to which this app should be deployed.
8+
name: "edgio-v7-ef-jwt-validation-example",
9+
10+
// The name of the organization in Edgio to which this app should be deployed.
11+
// organization: 'my-organization-name',
12+
13+
// Overrides the default path to the routes file. The path should be relative to the root of your app.
14+
// routes: 'routes.js',
15+
16+
// When set to true, Edgio includes the deployment number in the cache key,
17+
// effectively purging the cache each time you deploy.
18+
purgeCacheOnDeploy: true,
19+
// If omitted this will default to the "Automatic Purging" configuration on the environment's Caching tab.
20+
// purgeCacheOnDeploy: false,
21+
22+
// Uncomment the following to specify environment specific configs
23+
// environments: {
24+
// production: {
25+
// hostnames: [{ hostname: 'www.mysite.com' }],
26+
// },
27+
// staging: {
28+
// hostnames: [{ hostname: 'staging.mysite.com' }],
29+
// origins: [
30+
// {
31+
// name: 'origin',
32+
// hosts: [{ location: 'staging-origin.mysite.com' }],
33+
// override_host_header: 'staging-origin.mysite.com',
34+
// tls_verify: {
35+
// use_sni: true,
36+
// sni_hint_and_strict_san_check: 'staging-origin.mysite.com',
37+
// },
38+
// shields: { us_east: 'DCD' },
39+
// },
40+
// ],
41+
// },
42+
// },
43+
44+
// Options for hosting serverless functions on Edgio
45+
serverless: {
46+
// // Set to true to include all packages listed in the dependencies property of package.json when deploying to Edgio.
47+
// // This option generally isn't needed as Edgio automatically includes all modules imported by your code in the bundle that
48+
// // is uploaded during deployment
49+
// includeNodeModules: true,
50+
51+
// Include additional paths that are dynamically loaded by your app at runtime here when building the serverless bundle.
52+
include: ['static'],
53+
},
54+
55+
// The maximum number of URLs that will be concurrently prerendered during deployment when static prerendering is enabled.
56+
// Defaults to 200, which is the maximum allowed value.
57+
// prerenderConcurrency: 200,
58+
59+
// A list of glob patterns identifying which source files should be uploaded when running edgio deploy --includeSources.
60+
// This option is primarily used to share source code with Edgio support personnel for the purpose of debugging. If omitted,
61+
// edgio deploy --includeSources will result in all files which are not gitignored being uploaded to Edgio.
62+
//
63+
// sources : [
64+
// '**/*', // include all files
65+
// '!(**/secrets/**/*)', // except everything in the secrets directory
66+
// ],
67+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const path = require('path')
2+
const express = require('express')
3+
4+
const PORT = process.env.PORT || 3000
5+
6+
const app = express()
7+
app.use(express.static(path.join(__dirname, 'static'), {
8+
extensions: ['html']
9+
}))
10+
11+
app.listen(PORT, () => {
12+
`Express server running on port ${PORT}.`
13+
})

0 commit comments

Comments
 (0)