-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Publishing example examples/v7-jwt-verification
- Loading branch information
1 parent
c025f5e
commit c760f17
Showing
11 changed files
with
14,939 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: 16 | ||
- 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}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Edgio generated build directory | ||
/.edgio | ||
|
||
/node_modules | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,50 @@ | ||
# edgio-v7-jwt-verification-example | ||
# JWT Verification using Edge Functions | ||
|
||
https://edgio-community-examples-v7-jwt-verification-test.glb.edgio.link/ | ||
|
||
## Description | ||
|
||
This repository provides example code for verifying JSON Web Tokens (JWT) using Edge Functions. It features an example of how to verify a JWT and return a 401 response if the token is invalid. | ||
|
||
## Prerequisites | ||
|
||
**NOTE**: To use this project, you must be an Edgio customer and signed up for the Edge Functions. See our [Edge Functions documentation](https://docs.edg.io/guides/v7/edge-functions) for information on activating this feature. | ||
|
||
The system requirements include Node.js v16 or higher, and a UNIX-like system (Linux or macOS). The project code is written in JavaScript. | ||
|
||
## 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 the example functions. | ||
|
||
To deploy the project to Edgio, use the command `npm run edgio:deploy`. Note that deployment to Edgio requires you to be | ||
logged into Edgio CLI which can be done via `npm run edgio login` and following the instructions. | ||
|
||
## Known Issues and Limitations | ||
|
||
Currently | ||
|
||
* We only support JavaScript-based code | ||
* Each request has a 60-second (wall time) timeout limit | ||
* Each request is limited to 50ms of CPU time | ||
* Each request is limited to 2MB of memory | ||
* An Edgio Function can make fetch requests only to origins defined in your property configuration | ||
file (`edgio.config.js`). | ||
|
||
We're looking forward to feedback from our customers about these limitations and how we can improve the product. | ||
|
||
## Support | ||
|
||
If you have any queries or face issues with this project, please don't hesitate to contact | ||
the [Edgio team](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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { Buffer } from 'buffer'; | ||
import * as Base64 from 'crypto-js/enc-base64url'; | ||
import { HmacSHA256, HmacSHA384, HmacSHA512 } from 'crypto-js'; | ||
|
||
// Function to decode base64 strings | ||
const base64decode = (str) => Buffer.from(str, 'base64').toString(); | ||
|
||
// Hashing functions mapped to JWT algorithms | ||
const hashLibraries = { | ||
HS256: HmacSHA256, | ||
HS384: HmacSHA384, | ||
HS512: HmacSHA512, | ||
}; | ||
|
||
export class JWT { | ||
constructor(token, secret) { | ||
const [header_base64, payload_base64, origSignature] = token.split('.'); | ||
|
||
this.header_base64 = header_base64; | ||
this.payload_base64 = payload_base64; | ||
|
||
try { | ||
// Decode header and payload from base64 | ||
this.header = JSON.parse(base64decode(header_base64)); | ||
this.payload = JSON.parse(base64decode(payload_base64)); | ||
} catch (e) { | ||
// Invalid payload or header, initialize empty objects | ||
this.header = {}; | ||
this.payload = {}; | ||
} | ||
|
||
this.origSignature = origSignature; | ||
this.hasher = hashLibraries[this.header.alg]; | ||
this.secret = secret; | ||
} | ||
|
||
// Validates the JWT token | ||
validate() { | ||
try { | ||
const calculatedSignature = Base64.stringify( | ||
this.hasher(`${this.header_base64}.${this.payload_base64}`, this.secret) | ||
); | ||
return calculatedSignature === this.origSignature; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
|
||
// Returns the payload object | ||
payloadObject() { | ||
return this.payload; | ||
} | ||
|
||
// Returns the algorithm used in JWT | ||
algUsed() { | ||
return this.header.alg; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { JWT } from './JWT.js'; | ||
|
||
/** | ||
* Handle an HTTP request to validate a JWT. | ||
* | ||
* @param {Request} request - The incoming HTTP request. | ||
* @param {any} context - Context providing runtime information. | ||
* @returns {Response} HTTP response with validation result. | ||
*/ | ||
export async function handleHttpRequest(request, context) { | ||
// Extract the JWT token from the request body | ||
const { token } = await request.json(); | ||
|
||
// Retrieve the secret key from environment variables | ||
const secret = context.environmentVars['JWT_SECRET'] || 'your-256-bit-secret'; | ||
|
||
// Initialize response structure | ||
const resp = { valid: false }; | ||
|
||
// Create JWT instance with the token and secret | ||
const jwt = new JWT(token, secret); | ||
|
||
// Validate the JWT | ||
const isValid = jwt.validate(); | ||
|
||
// If valid, update response with additional JWT info | ||
if (isValid) { | ||
resp.valid = true; | ||
resp.payload = jwt.payloadObject(); // Extract payload | ||
resp.alg = jwt.algUsed(); // Extract algorithm used | ||
} | ||
|
||
// Return the response with appropriate HTTP status code | ||
return new Response(JSON.stringify(resp), { | ||
status: isValid ? 200 : 401, // 200 OK for valid token, 401 for invalid | ||
headers: { 'Content-Type': 'application/json' }, // Set response content type | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// 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 = { | ||
// The name of the site in Edgio to which this app should be deployed. | ||
name: 'ef-jwt-verification', | ||
|
||
// 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 or omitted entirely, Edgio includes the deployment number in the cache key, | ||
// effectively purging the cache each time you deploy. | ||
purgeCacheOnDeploy: true, | ||
// purgeCacheOnDeploy: false, | ||
|
||
origins: [ | ||
{ | ||
// The name of the backend origin | ||
name: 'origin', | ||
|
||
// Use the following to override the host header sent from the browser when connecting to the origin | ||
override_host_header: 'httpbin.org', | ||
|
||
// The list of origin hosts to which to connect | ||
hosts: [ | ||
{ | ||
// The domain name or IP address of the origin server | ||
location: 'httpbin.org', | ||
}, | ||
], | ||
|
||
tls_verify: { | ||
use_sni: true, | ||
sni_hint_and_strict_san_check: 'httpbin.org', | ||
}, | ||
|
||
// Uncomment the following to configure a shield | ||
// shields: { us_east: 'DCD' }, | ||
}, | ||
], | ||
|
||
// 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: ['views/**/*'], | ||
// }, | ||
|
||
// 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 | ||
// ], | ||
}; |
Oops, something went wrong.