-
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
Secret callback revisited #480
Conversation
Without the more contentious 'none'-changes
I should really add a editor.config and eslint to this project ;-)
…er/node-jsonwebtoken into add-secret-for-callback
@@ -59,23 +59,9 @@ module.exports = function (jwtString, secretOrPublicKey, options, callback) { | |||
return done(new JsonWebTokenError('secret or public key must be provided')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should move these ^ asserts inside the getSecrect
callback too, since you could have secretOrPublicKey
here but it could be a function that returns value / no-value later on. I mean:
var hasSignature = parts[2].trim() !== '';
if (!hasSignature && secretOrPublicKey){
return done(new JsonWebTokenError('jwt signature is required'));
}
if (hasSignature && !secretOrPublicKey) {
return done(new JsonWebTokenError('secret or public key must be provided'));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do believe, as the other PR-owner, that the jws-package already handles these cases. But will move them anyway ;-)
verify.js
Outdated
var payload; | ||
|
||
try { | ||
payload = decode(jwtString); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 wasn't this the decode
you wanted to clean in favor of the decode(..., { complete: true })
call you add at the beginning of the verify()
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI Not sure why but in github if I see the diff omitting whitespaces it shows me you removed this, however, in the normal view or even if I click in View button for this file I can still see this decode call
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, should be okay now :)
README.md
Outdated
@@ -197,6 +198,17 @@ jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) { | |||
// if token alg != RS256, err == invalid signature | |||
}); | |||
|
|||
// Verify using getKey callback | |||
function getKey(header, callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to use this function for JWK + openid cases we would need to add the issuer as well.
The options are:
- We add it here like
getKey(header, issuer, callback)
, and think if we want to check the issuer, if passed in options, before even calling thegetSecret
function. - Leave it as is in this PR. Give support for that in a different one by checking the length of
getKey
function (to see if the caller expects only header and callback or header, issuer and callback)
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the sake of progress, i would like to keep it as is. Let's make an separate issue for it and i will pick it up after this one ;-)
README.md
Outdated
@@ -29,6 +29,7 @@ $ npm install jsonwebtoken | |||
|
|||
`secretOrPrivateKey` is a string, buffer, or object containing either the secret for HMAC algorithms or the PEM | |||
encoded private key for RSA and ECDSA. In case of a private key with passphrase an object `{ key, passphrase }` can be used (based on [crypto documentation](https://nodejs.org/api/crypto.html#crypto_sign_sign_private_key_output_format)), in this case be sure you pass the `algorithm` option. | |||
If `jwt.verify` is called asynchronous, `secretOrPublicKey` can be a function that should fetch the secret or public key. See below for a detailed example |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in wrong place, right? it should be under jwt.verify
section, where we should indicate secretOrPublicKey
can be a function too.
verify.js
Outdated
|
||
if (parts.length !== 3){ | ||
return done(new JsonWebTokenError('jwt malformed')); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be kept here, it refers to the token format, not secret related, there is no need to potentially call the getSecret
function if the jwt is a malformed
verify.js
Outdated
} catch (err) { | ||
return done(err); | ||
} | ||
var payload = decodedToken.payload; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
test/verify.tests.js
Outdated
|
||
it('simple callback', function (done) { | ||
var keyFunc = function(header, callback) { | ||
callback(undefined, key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just saw that even when you are passing the decodedToken
the tests pass. Can you assert here you get just the content of the header from the token?
verify.js
Outdated
} | ||
|
||
return done(null, payload); | ||
return getSecret(decodedToken, function(err, secretOrPublicKey) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 why do you pass all the decoded token now?, I think it was fine passing just the decodedToken.header
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we will be using both the header and the payload of the token now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, wait, yes. that is wrong.
verify.js
Outdated
|
||
return done(null, payload); | ||
else { | ||
getSecret = function(decodedToken, secretCallback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even if it is not used, can you rename it back to header
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JacoKoster I saw your last commit after this comment, but that commit does not address this (not sure if you realized about it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, i forgot this one.
README.md
Outdated
callback(null, key); | ||
} | ||
|
||
verify(token, getKey, options, function(err, decoded) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jwt.verify
README.md
Outdated
@@ -197,6 +198,17 @@ jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) { | |||
// if token alg != RS256, err == invalid signature | |||
}); | |||
|
|||
// Verify using getKey callback | |||
function getKey(header, callback) { | |||
// fetch secret or public key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add some comment encouraging the users to cache the key with the kid so they avoid fetching it multiple times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add https://github.com/auth0/node-jwks-rsa as an example to load the keys, that should make it more clear.
verify.js
Outdated
return done(e); | ||
} | ||
|
||
if (!valid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please be consistent on the braces usage. A few lines above this one, another one liner if clause uses them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed this as well, but because it was already on master this way. I was planning to add eslint and fixing it in one go.
verify.js
Outdated
}); | ||
}); | ||
|
||
if (!match) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
braces
try { | ||
decodedToken = jws.decode(jwtString); | ||
decodedToken = decode(jwtString, { complete: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this {complete:true}
option wasn't being passed before. How does that affect the output @ziluvatar ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's mostly the same, however, our decode implementation tries to parse always the JSON (if string), the jws.decode
only does it when the type is JWT
. With this and other change afterwards we reduce the amount of parsing to half.
verify.js
Outdated
}; | ||
} | ||
|
||
return getSecret(header, function(err, secretOrPublicKey) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't enough with the kid
? What's on the header
that the user might want to use for key retrieval?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may want to use other headers to find the key: https://tools.ietf.org/html/rfc7515#page-10
LGTM 👨🎓 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will release this on Monday as a new minor version. (I don't want to publish anything on Friday :) )
@@ -67,6 +69,90 @@ describe('verify', function() { | |||
}); | |||
}); | |||
|
|||
describe('secret or token as callback', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is not properly indented with the rest of the file and doesn't follow the newly introduced .editorconfig
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to make this a thing with #486
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @jfromaniello on this one. Since the bad indentation is introduced in this PR there's no need to wait for a different one to fix it.
🎉 Released on v8.3.0!! Awesome work @JacoKoster 👏 |
Based on PR 413, without breaking existing functionality.
Added features
Performance improvements
Dependencies
See issue 406