-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for JWK #43
Comments
brianloveswords/node-jws does the actual signing. @awlayton made a node module that injects jwk support into node-jws (and therefore) node-jsonwebtoken. https://github.com/OADA/node-jws-jwk Maybe node-jws should incorporate @awlayton's work upstream. |
Brightspace/node-jwk-to-pem looks like a nice solution for JWK support. |
I ended up using dannycoates/pem-jwk to do JWK with jsonwebtoken. |
@RCanine Yep, using it exactly for this use-case, as suggested by the example. Might also check out https://github.com/Brightspace/node-jwk-allowed-algorithms for a better solution than the |
Are there actual plans to support this? The issue has been open for years and looks quite stale... |
This PR could open the door for this, since you would have an async way to load the secret/key based on headers (kid) & payload (issuer). |
are there any updates on this? this issue has been open for 4 yrs now 😅 |
I have been working to make JWK a thing and with the introduction of #480 this should be a breeze. Especially if you combine it with either https://www.npmjs.com/package/jwks-rsa or https://www.npmjs.com/package/jwks-client :-) @ziluvatar : I think this can be closed :-) |
As @JacoKoster said this can be implemented using v8.3.0+ passing a function as |
I'm a few years late to the discussion, but I was just searching to figure out how to do this myself, as I was expecting that Then I started doing research and looking into things based on the comments here and I figure I'll just sum up a few things. First, I'm a bit of an odd duck in that I work a lot on small devices (and I'm old school), so writing vanilla js and reducing dependencies is more important to me than to most people. I've also become even more dependency-phobic in the wake of the malicious code that was included with npm's most popular projects this past year. JWK-to-PEM (RSA, ECDSA)Although there are many libraries out there that do JWK-to-PEM and PEM-to-JWK, they're kinda half-baked (i.e. only do RSA or only do JWK-to-PEM or only public keys) and have huge dependency chains. Because of that I dug into node's new RSA and ECDSA APIs (added mid-v10) a while back and created tiny, lightweight libs that to do this sort of thing in just a few kilobytes, rather than megabytes (due to node's native APIs and barebones ASN.1 handling): Example: // barebones dependencies
var JWT = require('jsonwebtoken');
var Eckles = require('eckles'); // EC support
var Rasha = require('rasha'); // RSA support // A wrapper that handles JWKs
function verifyWithJwk(jwt, jwk) {
var pem;
if ('EC' === jwk.kty) {
pem = Eckles.exportSync({ jwk: jwk });
} else if ('RSA' === jwk.kty) {
pem = Rasha.exportSync({ jwk: jwk });
} else {
throw new Error("Expected EC or RSA key but got '" + jwk.kty + "'");
}
return JWT.verify(jwt, pem);
} // Usage example
try {
verifyWithJwk(jwt, jwk);
} catch(e) {
throw e;
} Example w/ Express: var JWT = require('jsonwebtoken');
var Eckles = require('eckles'); // EC support
var Rasha = require('rasha'); // RSA support
var request = require('@coolaj86/urequest'); // 0-dependency API-compatible drop-in for request
var express = require('express');
var app = express();
// same verify function as shown above
function verifyWithJwk(jwt, jwk) {
var pem;
if ('EC' === jwk.kty) {
pem = Eckles.exportSync({ jwk: jwk });
} else if ('RSA' === jwk.kty) {
pem = Rasha.exportSync({ jwk: jwk });
} else {
throw new Error("Expected EC or RSA key but got '" + jwk.kty + "'");
}
return JWT.verify(jwt, pem);
}
app.use('/authorized_endpoint', function (req, res, next) {
// Grab the token from the headers
var jwt = (req.headers.authorization||'').replace('Bearer ', '');
// TODO: we'd want to cache keys so we don't fetch them every time
request({ url: "https://example.com/oidc/jwks/", json: true }, function (resp) {
var jwk = resp.body.keys[0];
try {
verifyWithJwk(jwt, jwk);
} catch(e) {
// express will catch this and show the user an error
throw e;
}
// Let the user know the token is invalid
res.send({ verified: true });
});
}); Because they're so small (and more-or-less complete) I vendor them rather than including them as dependencies. So they do get about 20k+ downloads per week, but directly committed into more popular packages like greenlock and rsa-compat that use them. OIDC & Auth0 Key FetchingIf you're using the Open ID Connect
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) {
console.log(result.jwk);
console.log(result.thumprint);
console.log(result.pem);
jwt.verify(jwt, pem);
}); jwks-rsaWhat I like about the In fact, I'd probably use it myself if it weren't for the dependency on jwks-ecdsaThis module is built on outdated code that has dependencies which are no longer necessary (except for special use cases that you probably don't have). It also uses |
Hi @solderjs, AJ, I can see you're the author of rasha and eckles, i've recently looked into using those for a light-on-the-dependencies JOSE replacement for https://github.com/cisco/node-jose dependency for my own projects (oidc client and provider) I am building that's purely for recent node versions with KeyObject support where I don't intend to maintain javascript fallbacks (such as node-jose does with forge). // Rant alert Here's my gripe with the current jwk/jose/crypto node ecosystem.
Now on to supporting JWKs with node-jsonwebtoken, I'm all for it for the convenience and for one-time jwk use. BUT, knowing what the cost of js jwk <> asn1 <> pem is, followed up by re-parsing the PEM in openssl this adds up to a lot of time not doing the actual operation and just preparing keys which makes me think i'm better off just using the PEM or in the future an already parsed KeyObject. ad rasha and eckles, I took a stab at those packages, very impressive result, much ❤️ for the work you've put in. I wanted to use them for the pure node jose package because of the lack of dependencies they have, but alas
The same would apply to I'd also separate JWKS and JWK for the sake of this issue, bundling |
@panva I could add P-521 fairly easily, but is there a significant portion of developers actually using it?Only P-256 and P-384 are actually part of the NIST spec. P-521 is not. Adding support would merely require adding another header match in the code and I think the byte length is handled differently because it's odd rather than even. Duplicates some code, but not that big of a deal. I've also just published https://www.npmjs.com/package/keyfetch, which handles fetching from OIDC and Auth0 JWKs URLs and converting to PEM. I could be talked out of the telemetry if it really made that much difference. npm stats are very limited (and inaccurate). One of the surprising things I learned about some of my projects once I added telemetry was just how many people use node on Windows. Lastly, why are you using node if performance on conversion operations is so critical? Why not use Go or Rust? |
The choice of language of our customers or even internally in Auth0 varies, but if someone's to use node.js I believe they should be aware they can get way more out of their systems if they just don't convert key formats over and over and use node-jws/node-jwa just released with keyobject support, i plan on updating jsonwebtoken with its support as well, plus updating the documentation to point all of the above out
+1 on getting rid of it for rasha and eckles, as i wrote to you some weeks ago in an email, i believe you're packing these as a dependency in your other packages so you get much needed telemetry out of the box of those, don't you? That being said in order for us to pack it with |
Is this still going to be implemented? I'm currently using https://github.com/Brightspace/node-jwk-to-pem for the meantime. |
@root/keypairs is perhaps a more optimal solution, but requires node v10.12+. @panva: this version does not have telemetry. UsageA brief introduction to the APIs: // generate a new keypair as jwk
// (defaults to EC P-256 when no options are specified)
Keypairs.generate().then(function(pair) {
console.log(pair.private);
console.log(pair.public);
}); // JWK to PEM
// (supports various 'format' and 'encoding' options)
return Keypairs.export({ jwk: pair.private, format: 'pkcs8' }).then(function(
pem
) {
console.log(pem);
}); // PEM to JWK
return Keypairs.import({ pem: pem }).then(function(jwk) {
console.log(jwk);
}); // Thumbprint a JWK (SHA256)
return Keypairs.thumbprint({ jwk: jwk }).then(function(thumb) {
console.log(thumb);
}); // Sign a JWT (aka compact JWS)
return Keypairs.signJwt({
jwk: pair.private
, iss: 'https://example.com'
, exp: '1h'
// optional claims
, claims: {
, sub: 'jon.doe@gmail.com'
}
}); By default ECDSA keys will be used since they've had native support in node More at https://git.rootprojects.org/root/keypairs.js/src/branch/master/README.md |
I am wondering, if there are any plans to support signature validation with JSON Web Key:
https://tools.ietf.org/html/draft-ietf-jose-json-web-key-38
Here is an example JWK:
https://authorize.smartplatforms.org/jwk
The text was updated successfully, but these errors were encountered: