Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

get-jwks

Package Overview
Dependencies
Maintainers
35
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

get-jwks - npm Package Compare versions

Comparing version 2.1.0 to 3.0.0

test/cache.spec.js

8

package.json
{
"name": "get-jwks",
"version": "2.1.0",
"version": "3.0.0",
"description": "Fetch utils for JWKS keys",

@@ -10,3 +10,3 @@ "main": "src/get-jwks.js",

"scripts": {
"test": "tap",
"test": "tap --files=test/**/*.spec.js",
"lint": "eslint src/**/*.js test/**/*.js",

@@ -40,2 +40,6 @@ "ci": "npm run lint && tap --no-color --reporter=spec --coverage-report=json --coverage-report=text --100 test/*.spec.js test/**/*.spec.js"

"eslint-plugin-promise": "^4.3.1",
"fast-jwt": "^1.1.2",
"fastify": "^3.12.0",
"fastify-jwt": "^2.3.0",
"jsonwebtoken": "^8.5.1",
"nock": "^13.0.7",

@@ -42,0 +46,0 @@ "node-cache": "^5.1.2",

@@ -9,4 +9,2 @@ # get-jwks

Just run:
```bash

@@ -18,2 +16,4 @@ npm install get-jwks

### getJwk
```javascript

@@ -24,3 +24,3 @@ const buildGetJwks = require('get-jwks')

const secret = await getJwks.getSecret({
const jwk = await getJwks.getJwk({
domain: 'https://exampe.com/',

@@ -31,19 +31,31 @@ alg: 'token_alg',

// to clear the secret in cache
getJwks.clearCache()
```
Calling the asynchronous function `getJwk` will fetch the [JSON Web Key](https://tools.ietf.org/html/rfc7517), and verify if any of the public keys matches the `alg` and `kid` values of your JWT token. It will cache the matching key so if called again it will not make another request to retrieve a JWKS.
- `domain`: A string containing the domain (ie: `https://www.example.com/`) from which the library should fetch the JWKS. `get-jwks` will add the JWKS location (`.well-known/jwks.json`) to form the final url (ie: `https://www.example.com/.well-known/jwks.json`).
- `alg`: The alg header parameter represents the cryptographic algorithm used to secure the token. You will find it in your decoded JWT.
- `kid`: The kid is a hint that indicates which key was used to secure the JSON web signature of the token. You will find it in your decoded JWT.
### getPublicKey
### getSecret
```javascript
const buildGetJwks = require('get-jwks')
Calling the `getSecret` will fetch the [JSON Web Key](https://tools.ietf.org/html/rfc7517), Set and verify if any of the public keys matches the `alg` and `kid` values of your JWT token. And it will cache the secret so if called again it will not make another http request to return the secret. It is asynchronous.
const getJwks = buildGetJwks()
- `domain`: A string containing the domain (ie: `https://www.example.com/`) from which the library should fetch the JWKS. `get-jwks` will add the JWKS location (`.well-known/jwks.json`) to form the final url (ie: `https://www.example.com/.well-known/jwks.json`).
- `alg`: The alg header parameter represents the cryptographic algorithm used to secure the token. You will find it in your decoded JWT.
- `kid`: The kid is a hint that indicates which key was used to secure the JSON web signature of the token. You will find it in your decoded JWT.
const publicKey = await getJwks.getPublicKey({
domain: 'https://exampe.com/',
alg: 'token_alg',
kid: 'token_kid'
})
```
Calling the asynchronous function `getPublicKey` will run the `getJwk` function to retrieve a matching key, then convert it to a PEM public key. It requires the same arguments as `getJwk`.
### clearCache
Clears the contents of the cache
```javascript
getJwks.clearCache()
```
Clears all contents of the cache

@@ -65,2 +77,33 @@ ### Optional cache constuctor

## Integration Examples
### fastify-jwt
[fastify-jwt](https://github.com/fastify/fastify-jwt) is a Json Web Token plugin for [Fastify](https://www.fastify.io/).
The following example includes a scenario where you'd like to varify a JWT against a valid JWK on any request to your Fastify server. Any request with a valid JWT auth token in the header will return a successful response, otherwise will respond with an authentication error.
```javascript
const Fastify = require('fastify')
const fjwt = require('fastify-jwt')
const buildGetJwks = require('get-jwks')
const fastify = Fastify()
const getJwks = buildGetJwks()
fastify.register(fjwt, {
decode: { complete: true },
secret: (request, token, callback) => {
const { header: { kid, alg }, payload: { iss } } = token
getJwks.getPublicKey({ kid, domain: iss, alg })
.then(publicKey => callback(null, publicKey), callback)
}
})
fastify.addHook('onRequest', async (request, reply) => {
await request.jwtVerify()
})
fastify.listen(3000)
```

@@ -7,4 +7,4 @@ 'use strict'

const MISSING_KEY_ERROR = 'No matching key found in the set.'
const NO_KEYS_ERROR = 'No keys found in the set.'
const MISSING_JWK_ERROR = 'No matching JWK found in the set.'
const NO_JWKS_ERROR = 'No JWKS found in the response.'

@@ -16,18 +16,18 @@ function buildGetJwks (cacheProps = {}) {

async function getSecret (signatures) {
async function getPublicKey (signatures) {
const key = await getJwk(signatures)
const publicKey = jwkToPem(key)
return publicKey
}
async function getJwk (signatures) {
const { domain, alg, kid } = signatures
const cacheKey = `${alg}:${kid}:${domain}`
const cachedSecret = cache.get(cacheKey)
const cachedJwk = cache.get(cacheKey)
if (cachedSecret) {
return cachedSecret
} else if (cachedSecret === null) {
// null is returned when a previous attempt resulted in the key missing in the JWKs - Do not attemp to fetch again
throw new Error(MISSING_KEY_ERROR)
if (cachedJwk) {
return cachedJwk
}
// ensure there's a trailing slash from the domain
const issuerDomain = domain.endsWith('/') ? domain : `${domain}/`
// Hit the well-known URL in order to get the key
const response = await fetch(`${issuerDomain}.well-known/jwks.json`, { timeout: 5000 })

@@ -40,3 +40,2 @@ const body = await response.json()

error.body = body
throw error

@@ -46,23 +45,18 @@ }

if (!body.keys || body.keys.length === 0) {
throw new Error(NO_KEYS_ERROR)
throw new Error(NO_JWKS_ERROR)
}
// Find the key with ID and algorithm matching the JWT token header
const key = body.keys.find(k => k.alg === alg && k.kid === kid)
const jwk = body.keys.find(k => k.alg === alg && k.kid === kid)
if (!key) {
// Mark the key as missing
cache.set(cacheKey, null)
throw new Error(MISSING_KEY_ERROR)
if (!jwk) {
throw new Error(MISSING_JWK_ERROR)
}
const secret = jwkToPem(key)
// Save the key in the cache
cache.set(cacheKey, secret)
return secret
cache.set(cacheKey, jwk)
return jwk
}
return {
getSecret,
getPublicKey,
getJwk,
clearCache: () => cache.clear(),

@@ -69,0 +63,0 @@ cache

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc