AWS Cognito JWT 令牌验证

Posted

技术标签:

【中文标题】AWS Cognito JWT 令牌验证【英文标题】:AWS Cognito JWT token validation 【发布时间】:2018-03-07 21:02:16 【问题描述】:

我正在尝试基于 AWS Cognito JWT 令牌强制执行安全性,来源位于 https://github.com/IxorTalk/ixortalk.aws.cognito.jwt.security.filter。

但我担心,这是每个文档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

上面写着“ID 令牌在用户验证后一小时过期。过期后,您不应在客户端或 Web API 中处理 ID 令牌。”

我在日志中看到的错误是什么, com.nimbusds.jwt.proc.BadJWTException:过期的 JWT。我假设 JWT 令牌已经过期,我将如何成功执行基于令牌的授权?

【问题讨论】:

你使用刷新令牌来获取新的id+刷新+访问令牌。 【参考方案1】:

如果你使用Java,我的编程方式是这样的,

    // Parse the Cognito Keys and get the key by kid
    // Key is just a class that is used for parsing JSON to POJO
    Key key = this.keyService.getKeyByKeyId(JWT.decode(token).getKeyId());

    // Use Key's N and E
    BigInteger modulus = new BigInteger(1, Base64.decodeBase64(key.getN()));
    BigInteger exponent = new BigInteger(1, Base64.decodeBase64(key.getE()));

    // Create a publick key
    PublicKey publicKey = null;
    try 
        publicKey = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, exponent));
     catch (InvalidKeySpecException e) 
        // Throw error
     catch (NoSuchAlgorithmException e) 
        // Throw error
    

    // get an algorithm instance
    Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) publicKey, null);

    // I verify ISS field of the token to make sure it's from the Cognito source
    String iss = String.format("https://cognito-idp.%s.amazonaws.com/%s", REGION, POOL_ID);

    JWTVerifier verifier = JWT.require(algorithm)
            .withIssuer(iss)
            .withClaim("token_use", "id") // make sure you're verifying id token
            .build();

    // Verify the token
    DecodedJWT jwt = verifier.verify(token);

    // Parse various fields
    String username = jwt.getClaim("sub").asString();
    String email = jwt.getClaim("email").asString();
    String phone = jwt.getClaim("phone_number").asString();
    String[] groups = jwt.getClaim("cognito:groups").asArray(String.class);

我正在使用这个 repo 来验证和解析令牌,

    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.4.1</version>
    </dependency>

确保您正在导入以下内容,

    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTVerifier;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.exceptions.JWTDecodeException;
    import com.auth0.jwt.interfaces.DecodedJWT;

    import java.math.BigInteger;
    import java.security.KeyFactory;
    import java.security.NoSuchAlgorithmException;
    import java.security.PublicKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.RSAPublicKeySpec;
    import org.apache.commons.codec.binary.Base64;

如果令牌已过期,则不会更改。

【讨论】:

【参考方案2】:

您需要刷新令牌,它可以帮助您获得新的身份和访问令牌。 Cognito JS SDK 会自动刷新令牌。

现在在您的情况下,您似乎需要调用 RefreshToken 并添加检查以查看令牌是否已过期。

身份/访问令牌带有过期时间,因此您可以在使用它们之前在应用程序中本地执行此操作。

【讨论】:

嗨,cognito 返回刷新令牌和其他数据。我是否需要不断检查 id 令牌是否过期并在过期时请求它?

以上是关于AWS Cognito JWT 令牌验证的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 上验证 AWS id 令牌

如何在 Go 中验证来自 AWS Cognito 的 JWT 令牌?

AWS Cognito 如何验证我自己的 IdP 颁发的身份令牌?

我是不是需要在 Lambda 和 API 网关中验证 AWS Cognito 令牌?

AWS Cognito:将自定义声明/属性添加到 JWT 访问令牌

更改 AWS Cognito 访问令牌 JWT 中的加密算法