执行授权码授予流程
假设你:
您的浏览器应该重定向到<your-redirect-uri>?code=4dd94e4f-3323-471e-af0f-dc52a8fe98a0
现在您需要将该代码传递到您的后端并让它为您请求令牌。
POST https://<your-domain>.auth.us-west-2.amazoncognito.com/oauth2/token
- 将您的
Authorization 标头设置为 Basic 并根据您在 AWS Cognito 中配置的应用程序客户端使用 username=<app client id> 和 password=<app client secret>
- 在您的请求正文中设置以下内容:
grant_type=authorization_code
code=<your-code>
client_id=<your-client-id>
redirect_uri=<your-redirect-uri>
如果成功,您的后端应该会收到一组 base64 编码的令牌。
{
id_token: '...',
access_token: '...',
refresh_token: '...',
expires_in: 3600,
token_type: 'Bearer'
}
现在,根据documentation,您的后端应该通过以下方式验证 JWT 签名:
- 解码 ID 令牌
- 将本地密钥 ID(孩子)与公共孩子进行比较
- 使用公钥来验证使用您的 JWT 库的签名。
由于 AWS Cognito 为每个用户池生成两对 RSA 加密密钥,因此您需要确定用于加密令牌的密钥。
这是一个演示验证 JWT 的 NodeJS sn-p。
import jsonwebtoken from 'jsonwebtoken'
import jwkToPem from 'jwk-to-pem'
const jsonWebKeys = [ // from https://cognito-idp.us-west-2.amazonaws.com/<UserPoolId>/.well-known/jwks.json
{
"alg": "RS256",
"e": "AQAB",
"kid": "ABCDEFGHIJKLMNOPabc/1A2B3CZ5x6y7MA56Cy+6ubf=",
"kty": "RSA",
"n": "...",
"use": "sig"
},
{
"alg": "RS256",
"e": "AQAB",
"kid": "XYZAAAAAAAAAAAAAAA/1A2B3CZ5x6y7MA56Cy+6abc=",
"kty": "RSA",
"n": "...",
"use": "sig"
}
]
function validateToken(token) {
const header = decodeTokenHeader(token); // {"kid":"XYZAAAAAAAAAAAAAAA/1A2B3CZ5x6y7MA56Cy+6abc=", "alg": "RS256"}
const jsonWebKey = getJsonWebKeyWithKID(header.kid);
verifyJsonWebTokenSignature(token, jsonWebKey, (err, decodedToken) => {
if (err) {
console.error(err);
} else {
console.log(decodedToken);
}
})
}
function decodeTokenHeader(token) {
const [headerEncoded] = token.split('.');
const buff = new Buffer(headerEncoded, 'base64');
const text = buff.toString('ascii');
return JSON.parse(text);
}
function getJsonWebKeyWithKID(kid) {
for (let jwk of jsonWebKeys) {
if (jwk.kid === kid) {
return jwk;
}
}
return null
}
function verifyJsonWebTokenSignature(token, jsonWebKey, clbk) {
const pem = jwkToPem(jsonWebKey);
jsonwebtoken.verify(token, pem, {algorithms: ['RS256']}, (err, decodedToken) => clbk(err, decodedToken))
}
validateToken('xxxxxxxxx.XXXXXXXX.xxxxxxxx')