Reputation: 5375
I'm trying to figure out how to verify a user's IDToken obtained from AWS Cognito Identity authenticateUser call.
Following the steps found here:https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html#amazon-cognito-identity-user-pools-using-id-and-access-tokens-in-web-api I was able to get to the point where I have the user's ID Token and I've decoded the header and body.
Given an IDToken this is what my header and body look like:
header:
{
typ: 'JWT',
alg: 'RS256',
kid: '...'
}
body:
{
sub: 'abcd...',
aud: 'abcdefg...',
email_verified: true,
token_use: 'id',
auth_time: 1491491773,
iss: 'https://cognito-idp.us-east-1.amazonaws.com/us-east-...',
'cognito:username': 'username',
exp: 1491495373,
iat: 1491491773,
email: '[email protected]'
}
Then the third part of the IDToken is the signature:
'T6tjQ...' // big long encoded string
The part I'm stuck on is actually verifying the signature against my signing key. I can't seem to get this part working. Right now I'm trying to use the njwt
node module found here: https://www.npmjs.com/package/njwt.
Given IDToken
as a 3 part .
separated base64 encoded string, and secretKey
as the following Javascript object:
{
alg: 'RS256',
e: '...',
kid: '...', // matches kid of IDToken
kty: 'RSA',
n: 'abcdefg...', // Appears to be some big long encoded string
use: 'sig'
}
This is what I've tried with the njwt
node module:
njwt.verify(IDToken, secretKey, 'RS256', function(err, verifiedJwt)
{
if (err)
{
console.log(err);
}
else
{
console.log('Verified');
}
});
When I try it this way I get:
TypeError: Not a buffer
at Verify.verify (crypto.js:426:24)
at .../node_modules/njwt/index.js:406:10
at Verifier.defaultKeyResolver (.../node_modules/njwt/index.js:72:10)
at Verifier.verify (.../node_modules/njwt/index.js:375:15)
at Object.jwtLib.verify (.../node_modules/njwt/index.js:457:21)
at repl:1:6
at REPLServer.self.eval (repl.js:110:21)
at repl.js:249:20
at REPLServer.self.eval (repl.js:122:7)
at Interface.<anonymous> (repl.js:239:12)
So I thought maybe I need to pass in secretKey.n
instead of secretKey
like so:
njwt.verify(IDToken, secretKey.n, 'RS256', function(err, verifiedJwt)
{
if (err)
{
console.log(err);
}
else
{
console.log('Verified');
}
});
When I try it this way I get:
139980866705216:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:696:Expecting: CERTIFICATE
Followed by my console.log(err);
:
{ [JwtParseError: Signature verification failed]
name: 'JwtParseError',
userMessage: 'Signature verification failed',
message: 'Signature verification failed',
jwtString: 'abcdefg...',
parsedHeader: {
typ: 'JWT',
alg: 'RS256',
kid: '...'
},
parsedBody: {
sub: 'abcd...',
aud: 'abcdefg...',
email_verified: true,
token_use: 'id',
auth_time: 1491491773,
iss: 'https://cognito-idp.us-east-1.amazonaws.com/us-east-...',
'cognito:username': 'username',
exp: 1491495373,
iat: 1491491773,
email: '[email protected]'
},
innerError: undefined }
How should I be passing in secretKey
? What should secretKey
be and what should it look like? To be quite honest I'm not even sure what njwt.verify
is expecting.
Upvotes: 1
Views: 1725
Reputation: 5375
It looks like the issue was that njwt.verify
was expecting a public RSA key. I had to convert my JWK Set object to a public RSA key. I did that by using the jwk-to-pem
node module.
Given the same secretKey
from the question:
var jwkToPem = require('jwk-to-pem');
var pem = jwkToPem(secretKey);
njwt.verify(IDToken, pem, 'RS256', function(err, verifiedJwt)
{
if (err)
{
console.log(err);
}
else
{
console.log('Verified');
}
});
Success!
Upvotes: 1