Skip to content

Commit

Permalink
Publishing example examples/v7-ef-jwt-validation
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Aug 14, 2024
1 parent 49cda65 commit aafeade
Show file tree
Hide file tree
Showing 11 changed files with 11,056 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**NOTICE TO CONTRIBUTORS**

This repository is not actively monitored and any pull requests made to this repository will be closed/ignored.

Please submit the pull request to [edgio-docs/edgio-examples](https://github.com/edgio-docs/edgio-examples) instead.
18 changes: 18 additions & 0 deletions .github/workflows/edgio.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Deploy to Edgio

on:
workflow_dispatch:
push:

jobs:
deploy-to-edgio:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: if [ -f yarn.lock ]; then yarn install; else npm ci; fi
- run: if [ -f yarn.lock ]; then yarn edgio:deploy -- --token=$EDGIO_DEPLOY_TOKEN; else npm run edgio:deploy -- --token=$EDGIO_DEPLOY_TOKEN; fi
env:
EDGIO_DEPLOY_TOKEN: ${{secrets.EDGIO_DEPLOY_TOKEN}}
57 changes: 56 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,56 @@
# edgio-v7-ef-jwt-validation-example
# JWT Verification using Edge Functions

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.
- **Valid JWT:** Returns the decoded JWT.
- **Invalid JWT:** Returns a `401 Unauthorized` response.

Try it at:

https://edgio-community-examples-v7-ef-jwt-validation-live.glb.edgio.link/jwt

## Prerequisites

This JavaScript project requires:

- An Edgio account.
- Edge Functions activation. [Learn more about activation.](https://docs.edg.io/guides/v7/edge-functions)
- Node.js v18 or higher
- A UNIX-like system (Linux or macOS).

## Setup and Installation

1. Ensure you meet the prerequisites.
2. Clone the repository to your local machine.
3. Run `npm install` in the repository directory.

## Getting Started

After setting up the project, run `npm run edgio:dev` to start a local development server to test.

To deploy the project to Edgio, use the command `npm run edgio:deploy`. Deploying to Edgio requires you to be
logged into Edgio CLI which can be done via `npm run edgio login` and the following the instructions.

## Known Issues and Limitations

Edge functions:

- Must use JavaScript code.
- May only submit fetch requests to origins defined within your property configuration
file (`edgio.config.js`).

[View additional limitations.](https://docs.edg.io/applications/edge_functions#limitations)

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.

ESxxx algorithms use a very slow elliptical curve algorithm and may take longer than is allowed to validate, even with increased limits.

## Support

If you have any queries or face issues with this project, [contact
us](https://edg.io/contact-support/).

## License

[Creative Commons Attribution 4.0 International Public License](LICENSE-CONTENT) for the documentation.

[MIT License](LICENSE-CODE) for the code.
54 changes: 54 additions & 0 deletions edge-functions/validate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { KJUR, KEYUTIL } from 'jsrsasign'
import { Buffer } from 'buffer'

// Set up some polyfills to allow this code to run locally and when deployed:
global.process = global.process || { env: {} }
const fromBase64 = (str) => Buffer.from(str, 'base64').toString()

export async function handleHttpRequest(request, context) {
Object.assign(process.env, context.environmentVars)

// Extract the toke and any other objects from the request.
const { token, ...other } = await request.json()

// Split out the header and payload from the cleartext token and determine the right algorithm to use.
const [header, payload] = token.split('.')
const { alg } = JSON.parse(fromBase64(header))

let validationComponent = null
let valid = false
const resp = { valid }

try {
// For HSxxx algorithms, the validation requires a plaintext secret key.
// For RSxxx, ESxxx, and PSxxx algorithms, a public key is required instead.
// The public key is expected to be part of the request payload and be named pubKey;
// the secret key SHOULD NOT be part of the payload.
// Note that for demo purposes (being able to set an arbitrary signing key) this
// version of the EF will use the secret from `pubKey` if it exists.
if (/^HS/i.test(alg)) {
if ('pubKey' in other) {
validationComponent = other.pubKey
} else {
validationComponent = process.env.JWT_SECRET
}
} else if (/^[REP]S/i.test(alg)) {
validationComponent = KEYUTIL.getKey(other.pubKey)
} else {
return new Response('Invalid JWT alg specified.', { status: 401 })
}

valid = KJUR.jws.JWS.verifyJWT(token, validationComponent, { alg: [alg] })
if (valid === true) {
// Only parse the payload if the signature is valid.
const decodedPayload = JSON.parse(fromBase64(payload))
Object.assign(resp, { valid, alg, payload: decodedPayload })
}
} catch (e) {
// Handle exceptions here.
}

return new Response(JSON.stringify(resp), {
status: valid ? 200 : 401
})
}
67 changes: 67 additions & 0 deletions edgio.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// This file was automatically added by edgio init.
// You should commit this file to source control.
// Learn more about this file at https://docs.edg.io/guides/edgio_config
module.exports = {
connector: '@edgio/express',

// The name of the site in Edgio to which this app should be deployed.
name: "edgio-v7-ef-jwt-validation-example",

// The name of the organization in Edgio to which this app should be deployed.
// organization: 'my-organization-name',

// Overrides the default path to the routes file. The path should be relative to the root of your app.
// routes: 'routes.js',

// When set to true, Edgio includes the deployment number in the cache key,
// effectively purging the cache each time you deploy.
purgeCacheOnDeploy: true,
// If omitted this will default to the "Automatic Purging" configuration on the environment's Caching tab.
// purgeCacheOnDeploy: false,

// Uncomment the following to specify environment specific configs
// environments: {
// production: {
// hostnames: [{ hostname: 'www.mysite.com' }],
// },
// staging: {
// hostnames: [{ hostname: 'staging.mysite.com' }],
// origins: [
// {
// name: 'origin',
// hosts: [{ location: 'staging-origin.mysite.com' }],
// override_host_header: 'staging-origin.mysite.com',
// tls_verify: {
// use_sni: true,
// sni_hint_and_strict_san_check: 'staging-origin.mysite.com',
// },
// shields: { us_east: 'DCD' },
// },
// ],
// },
// },

// Options for hosting serverless functions on Edgio
serverless: {
// // Set to true to include all packages listed in the dependencies property of package.json when deploying to Edgio.
// // This option generally isn't needed as Edgio automatically includes all modules imported by your code in the bundle that
// // is uploaded during deployment
// includeNodeModules: true,

// Include additional paths that are dynamically loaded by your app at runtime here when building the serverless bundle.
include: ['static'],
},

// The maximum number of URLs that will be concurrently prerendered during deployment when static prerendering is enabled.
// Defaults to 200, which is the maximum allowed value.
// prerenderConcurrency: 200,

// A list of glob patterns identifying which source files should be uploaded when running edgio deploy --includeSources.
// This option is primarily used to share source code with Edgio support personnel for the purpose of debugging. If omitted,
// edgio deploy --includeSources will result in all files which are not gitignored being uploaded to Edgio.
//
// sources : [
// '**/*', // include all files
// '!(**/secrets/**/*)', // except everything in the secrets directory
// ],
};
13 changes: 13 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const path = require('path')
const express = require('express')

const PORT = process.env.PORT || 3000

const app = express()
app.use(express.static(path.join(__dirname, 'static'), {
extensions: ['html']
}))

app.listen(PORT, () => {
`Express server running on port ${PORT}.`
})
Loading

0 comments on commit aafeade

Please sign in to comment.