Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sagi/workers-jwt
Generate JWTs on Cloudflare Workers using the WebCrypto API
https://github.com/sagi/workers-jwt
cloudflare cloudflare-workers jwt webcrypto workers
Last synced: 9 days ago
JSON representation
Generate JWTs on Cloudflare Workers using the WebCrypto API
- Host: GitHub
- URL: https://github.com/sagi/workers-jwt
- Owner: sagi
- License: mit
- Created: 2019-05-05T15:18:53.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2024-09-10T04:28:30.000Z (about 2 months ago)
- Last Synced: 2024-10-18T09:32:23.474Z (21 days ago)
- Topics: cloudflare, cloudflare-workers, jwt, webcrypto, workers
- Language: JavaScript
- Homepage: https://sagi.io
- Size: 1.91 MB
- Stars: 95
- Watchers: 2
- Forks: 9
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# workers-jwt
[`@sagi.io/workers-jwt`](https://www.npmjs.com/package/@sagi.io/workers-jwt) helps you
generate a `JWT` on Cloudflare Workers with the WebCrypto API. Helper function for GCP Service Accounts included.⭐ We use it at **[OpenSay](https://opensay.co/?s=workers-jwt)** to efficiently access Google's REST APIs with 1 round trip.
[![CircleCI](https://circleci.com/gh/sagi/workers-jwt.svg?style=svg)](https://circleci.com/gh/sagi/workers-jwt)
[![Coverage Status](https://coveralls.io/repos/github/sagi/workers-jwt/badge.svg?branch=master)](https://coveralls.io/github/sagi/workers-jwt?branch=master)
[![MIT License](https://img.shields.io/npm/l/@sagi.io/workers-jwt.svg?style=flat-square)](http://opensource.org/licenses/MIT)
[![version](https://img.shields.io/npm/v/@sagi.io/workers-jwt.svg?style=flat-square)](http://npm.im/@sagi.io/workers-jwt)## Installation
~~~
$ npm i @sagi.io/workers-jwt
~~~## API
We currently expose two methods: `getToken` for general purpose `JWT` generation
and `getTokenFromGCPServiceAccount` for `JWT` generation using a `GCP` service account.### **`getToken({ ... })`**
Function definition:
```js
const getToken = async ({
privateKeyPEM,
payload,
alg = 'RS256',
cryptoImpl = null,
headerAdditions = {},
}) => { ... }
```Where:
- **`privateKeyPEM`** is the private key `string` in `PEM` format.
- **`payload`** is the `JSON` payload to be signed, i.e. the `{ aud, iat, exp, iss, sub, scope, ... }`.
- **`alg`** is the signing algorithm as defined in [`RFC7518`](https://tools.ietf.org/html/rfc7518#section-3.1), currently only `RS256` and `ES256` are supported.
- **`cryptoImpl`** is a `WebCrypto` `API` implementation. Cloudflare Workers support `WebCrypto` out of the box. For `Node.js` you can use [`require('crypto').webcrypto` - see examples below and in the tests.
- **`headerAdditions`** is an object with keys and string values to be added to the header of the `JWT`.### **`getTokenFromGCPServiceAccount({ ... })`**
Function definition:
```js
const getTokenFromGCPServiceAccount = async ({
serviceAccountJSON,
aud,
alg = 'RS256',
cryptoImpl = null,
expiredAfter = 3600,
headerAdditions = {},
payloadAdditions = {}
}) => { ... }
```Where:
- **`serviceAccountJSON`** is the service account `JSON` object .
- **`aud`** is the audience field in the `JWT`'s payload. e.g. `https://www.googleapis.com/oauth2/v4/token`'.
- **`expiredAfter`** - the duration of the token's validity. Defaults to 1 hour - 3600 seconds.
- **`payloadAdditions`** is an object with keys and string values to be added to the payload of the `JWT`. Example - `{ scope: 'https://www.googleapis.com/auth/chat.bot' }`.
- **`alg`**, **`cryptoImpl`**, **`headerAdditions`** are defined as above.## Example
Suppose you'd like to use `Firestore`'s REST API. The first step is to generate
a service account with the "Cloud Datastore User" role. Please download the
service account and store its contents in the `SERVICE_ACCOUNT_JSON_STR` environment
variable.The `aud` is defined by GCP's [service definitions](https://github.com/googleapis/googleapis/tree/master/google)
and is simply the following concatenated string: `'https://' + SERVICE_NAME + '/' + API__NAME`.
More info [here](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#jwt-auth).For `Firestore` the `aud` is `https://firestore.googleapis.com/google.firestore.v1.Firestore`.
## Cloudflare Workers Usage
Cloudflare Workers expose the `crypto` global for the `Web Crypto API`.
~~~js
const { getTokenFromGCPServiceAccount } = require('@sagi.io/workers-jwt')const serviceAccountJSON = await ENVIRONMENT.get('SERVICE_ACCOUNT_JSON','json')
const aud = `https://firestore.googleapis.com/google.firestore.v1.Firestore`const token = await getTokenFromGCPServiceAccount({ serviceAccountJSON, aud} )
const headers = { Authorization: `Bearer ${token}` }
const projectId = 'example-project'
const collection = 'exampleCol'
const document = 'exampleDoc'const docUrl =
`https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents`
+ `/${collection}/${document}`const response = await fetch(docUrl, { headers })
const documentObj = await response.json()
~~~## Node Usage (version <=14)
We use the `node-webcrypto-ossl` package to imitate the `Web Crypto API` in Node.
~~~js
const { Crytpo }= require('node-webcrypto-ossl');
const cryptoImpl = new Crypto();
const { getTokenFromGCPServiceAccount } = require('@sagi.io/workers-jwt')const serviceAccountJSON = { ... }
const aud = `https://firestore.googleapis.com/google.firestore.v1.Firestore`const token = await getTokenFromGCPServiceAccount({ serviceAccountJSON, aud, cryptoImpl } )
<... SAME AS CLOUDFLARE WORKERS ...>
~~~## Node Usage (version 15+)
Node 15 introduces the [Web Crypto API](https://nodejs.org/api/webcrypto.html). When using NextJS, you may need to pass in the native Node `webcrypto` lib to get both SSR and webpack to work during dev mode.
~~~js
const { getTokenFromGCPServiceAccount } = require('@sagi.io/workers-jwt')const serviceAccountJSON = { ... }
const aud = 'https://firestore.googleapis.com/google.firestore.v1.Firestore';const token = await getTokenFromGCPServiceAccount({
serviceAccountJSON,
aud,
cryptoImpl: globalThis.crypto || require('crypto').webcrypto,
});<... SAME AS CLOUDFLARE WORKERS ...>
~~~