An easy, lightweight, and secure module for fetching JWK Public Keys and verifying JWTs. Great for OIDC, Auth0, JWKs URLs.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
AJ ONeal aba70bf0ff make Prettier 4年前
.gitignore v1.1.8: cleanup and support forced keys for verification 5年前
.prettierrc make Prettier 4年前
LICENSE v1.1.10: update package.json and LICENSE 5年前 make Prettier 4年前
keyfetch-test.js make Prettier 4年前
keyfetch.js make Prettier 4年前
package-lock.json v1.1.9: bump deps 5年前
package.json v1.2.1: better trusted issuer normalization 5年前


Lightweight support for fetching JWKs.

Fetches JSON native JWKs and exposes them as PEMs that can be consumed by the jsonwebtoken package (and node's native RSA and ECDSA crypto APIs).


Works great for

  • jsonwebtoken (Auth0)
  • OIDC (OpenID Connect)
  • .well-known/jwks.json (Auth0)
  • Other JWKs URLs

Crypto Support

  • JWT verification
  • RSA (all variants)
  • EC / ECDSA (NIST variants P-256, P-384)
  • esoteric variants (excluded to keep the code featherweight and secure)


npm install --save keyfetch


Retrieve a key list of keys:

var keyfetch = require("keyfetch");

keyfetch.oidcJwks("").then(function (results) {
    results.forEach(function (result) {

Quick JWT verification (for authentication):

var keyfetch = require("keyfetch");
var jwt = "...";

keyfetch.jwt.verify(jwt).then(function (decoded) {

JWT verification (for authorization):

var options = { issuers: [""], claims: { role: "admin" } };
keyfetch.jwt.verify(jwt, options).then(function (decoded) {

Verify a JWT with jsonwebtoken:

var keyfetch = require("keyfetch");
var jwt = require("jsonwebtoken");
var auth = "..."; // some JWT
var token = jwt.decode(auth, { json: true, complete: true });

if (!isTrustedIssuer(token.payload.iss)) {
    throw new Error("untrusted issuer");

keyfetch.oidcJwk(token.header.kid, token.payload.iss).then(function (result) {

    jwt.jwt.verify(jwt, { jwk: result.jwk });

Note: You might implement isTrustedIssuer one of these:

function isTrustedIssuer(iss) {
    return -1 !== ["", ""].indexOf(iss);
function isTrustedIssuer(iss) {
    return (
        /^https:/.test(iss) && /(\.|^)example\.com$/.test(iss) // must be a secure domain
    ); // can be or any subdomain


All API calls will return the RFC standard JWK SHA256 thumbprint as well as a PEM version of the key.

Note: When specifying id, it may be either kid (as in token.header.kid) or thumbprint (as in result.thumbprint).


Retrieves keys from a URL such as with the format { keys: [ { kid, kty, exp, ... } ] } and returns the array of keys (as well as thumbprint and jwk-to-pem).

// Promises [ { jwk, thumbprint, pem } ] or fails
keyfetch.jwk(id, jwksUrl);
// Promises { jwk, thumbprint, pem } or fails


If is used as issuerUrl it will resolve to and return the keys.

// Promises [ { jwk, thumbprint, pem } ] or fails
keyfetch.wellKnownJwk(id, issuerUrl);
// Promises { jwk, thumbprint, pem } or fails


If is used as issuerUrl then it will first resolve to and then follow jwks_uri to return the keys.

// Promises [ { jwk, thumbprint, pem } ] or fails
keyfetch.oidcJwk(id, issuerUrl);
// Promises { jwk, thumbprint, pem } or fails

Verify JWT

This can accept a JWT string (compact JWS) or a decoded JWT object (JWS).

This can be used purely for verifying pure authentication tokens, as well as authorization tokens.

keyfetch.jwt.verify(jwt, { strategy: "oidc" }).then(function (verified) {
    { protected: '...'  // base64 header
    , payload: '...'    // base64 payload
    , signature: '...'  // base64 signature
    , header: {...}     // decoded header
    , claims: {...}     // decoded payload

When used for authorization, it's important to specify which issuers are allowed (otherwise anyone can create a valid token with whatever any claims they want).

If your authorization claims can be expressed as exact string matches, you can specify those too.

keyfetch.jwt.verify(jwt, {
  strategy: 'oidc'
, issuers: [ '' ]
, claims: { role: 'admin', sub: 'abc', group: 'xyz' }
}).then(function (verified) {

  • strategy may be oidc (default) , auth0, or a direct JWKs url.
  • issuers must be a list of https urls (though http is allowed for things like Docker swarm)
  • claims is an object with arbitrary keys (i.e. everything except for the standard iat, exp, jti, etc)
  • exp may be set to false if you're validating on your own (i.e. allowing time drift leeway)
  • jwks can be used to specify a list of allowed public key rather than fetching them (i.e. for offline unit tests)
  • jwk same as above, but a single key rather than a list

Decode JWT

try {
  console.log( keyfetch.jwt.decode(jwt) );
} catch(e) {
{ protected: '...'  // base64 header
, payload: '...'    // base64 payload
, signature: '...'  // base64 signature
, header: {...}     // decoded header
, claims: {...}     // decoded payload

It's easier just to show the code than to explain the example.

keyfetch.jwt.decode = function (jwt) {
    // Unpack JWS from "compact" form
    var parts = jwt.split(".");
    var obj = {
        protected: parts[0],
        payload: parts[1],
        signature: parts[2]

    // Decode JWT properties from JWS as unordered objects
    obj.header = JSON.parse(Buffer.from(obj.protected, "base64")); = JSON.parse(Buffer.from(obj.payload, "base64"));

    return obj;

Cache Settings

    // set all keys at least 1 hour (regardless of jwk.exp)
    mincache: 1 * 60 * 60,

    // expire each key after 3 days (regardless of jwk.exp)
    maxcache: 3 * 24 * 60 * 60,

    // re-fetch a key up to 15 minutes before it expires (only if used)
    staletime: 15 * 60

There is no background task to cleanup expired keys as of yet. For now you can limit the number of keys fetched by having a simple whitelist.