Jared Price
Jared Price

Reputation: 5375

Verifying AWS Cognito JWT IDToken against a JWK Set with njwt

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

Answers (1)

Jared Price
Jared Price

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

Related Questions