I am trying out the log in function for the Cognito User Pool for my Web App. I was able to obtain the Token but I am not sure where to find the secret to decode it. I've read in one of the post that the secret is the secret Id for the App in the User Pool. However, for Javascript SDK, the secret id is blank. Does this mean my secret should also be blank? I tried this but I got a message that says "Error: PEM_read_bio_PUBKEY failed".
-
the key is available as the json key which you can download from the user pool. You then need to transform it to PEM key in order to use it to decode the JWT. – leo c Jul 05 '16 at 03:52
3 Answers
To correct the other answer: RS256 is an asymmetric algorithm and requires a public and a private key. Also see RS256 vs HS256: What's the difference? and https://en.wikipedia.org/wiki/RSA_(cryptosystem).
What is correct is that for verifying the JWT you do not need the private key that was used to sign it, only the public key made available by AWS under https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
.
-
3I got an array of Json from there, which attribute contains the public key for the token? trying out with the value in "n" attribute throws signature is invalid – Jefree Sujit Jun 11 '17 at 07:49
-
2@JefreeSujit The JWT will contain a "kid" (key ID), which decides the JWK to use from the `cognito-idp` request shown above. You then need the JWK's `n` (modulus) and `e` (public exponent) to convert to a "pem" formatted RSA public key. Here is a one-liner in scala (using java libraries) for the conversion (`n` & `e` are strings): `Base64.getEncoder.encodeToString(KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(new BigInteger(1, Base64.getUrlDecoder.decode(n)), new BigInteger(1, Base64.getUrlDecoder.decode(e)))).getEncoded)` – ecoe Jul 05 '18 at 15:53
-
Just want to summarize this topic with the snippet of code:
const jwkToPem = require('jwk-to-pem');
const requestify = require('requestify');
/**
* Get cognito's secret key
* @param {String} region
* @param {String} userPoolId
* @returns {Promise}
*/
function getPem(region, userPoolId) {
const jwkUrl = `https://cognito-idp.${region}.amazonaws.com/${userPoolId}/.well-known/jwks.json`;
return requestify.request(jwkUrl, { method: 'get', dataType: 'json'})
.then(res => res.getBody()['keys'].shift())
.then(jwk => jwkToPem(jwk))
;
}

- 3,413
- 2
- 21
- 41
-
1Good summary. But we will have to find the matching key from the keys array using kid. and then pass to jwkTOPem() – Swapnil Mhaske Sep 04 '20 at 12:23
-
AWS uses RS256 algorithm which does not require secret but public key to decode.
Here you will find JWKS of your pool: https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
(See http://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)
And here is described process of transforming JWK to the public key: https://mobile.awsblog.com/post/Tx3JK25U7Z9EUIU/Integrating-Amazon-Cognito-User-Pools-with-API-Gateway (under section "Understanding the code").

- 2,685
- 2
- 23
- 33
-
6sorry but this is plain wrong - RS256 is an asymmetric algorithm and requires a public and a private key. What would be correct is that for verifying the JWT you do not need the private key that was used to sign it. – B M Jan 11 '17 at 16:45
-
-
1I was answering the question which was "where to find the secret to decode it" (and not about general functioning of the RS256) so I consider my answer right. – JakubM Aug 16 '17 at 06:30
-
1