GithubHelp home page GithubHelp logo

sagi / workers-jwt Goto Github PK

View Code? Open in Web Editor NEW
95.0 2.0 9.0 1.89 MB

Generate JWTs on Cloudflare Workers using the WebCrypto API

Home Page: https://sagi.io

License: MIT License

JavaScript 100.00%
cloudflare-workers jwt cloudflare workers webcrypto

workers-jwt's Introduction

workers-jwt

@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 to efficiently access Google's REST APIs with 1 round trip.

CircleCI Coverage Status MIT License version

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:

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, 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:

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 and is simply the following concatenated string: 'https://' + SERVICE_NAME + '/' + API__NAME. More info here.

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.

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.

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. 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.

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 ...>

workers-jwt's People

Contributors

alexeichhorn avatar dependabot[bot] avatar omrilotan avatar rscotten avatar sagi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

workers-jwt's Issues

DataError: Invalid PKCS8 input.

I am trying to use a Cloudflare worker to host a GitHub app, but continue to receive this error:
DataError: Invalid PKCS8 input.

Here is my code:

const { getToken } = require('@sagi.io/workers-jwt')


async function handleRequest(req){
  var payload = {
    iat: Math.round(new Date().valueOf()/1000) - 60,
    exp: Math.round(new Date().valueOf()/1000) + (10*60),
    iss: '216732',
  }

  try{

    const token = await getToken({
      privateKeyPEM: RSA PRIVATE KEY,
      payload: payload,
      alg: 'RS256',
    })

  }catch(e){
      console.log(e)
  }

  return new Response( token )
}

What is wrong?

Validate JWT tokens and claims

A nice enhancement to this lib would be to bring it full circle and provide the capability to validate JWTs as well as generate them.

It should automatically validate all of the standard claims and provide a mechanism to allow custom validators for non-standard claims.

ECC keys would be great if supported for both JWT generation and validation.

Retrieval of public keys from JWKS urls with local cache of the pubkeys would be icing on the cake.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.