是否有针对aws cognito API的JWT验证的java示例?
我使用的是aws cognito用户池,在用户登录后,我在单页应用程序中获得了一个id令牌,这是预期的,然后对于每个请求,我需要在我的后端rest API中验证id令牌,它是java的,aws文档没有太多提到如何做 有什么例子吗 混淆包括:是否有针对aws cognito API的JWT验证的java示例?,java,amazon-web-services,jwt,aws-cognito,Java,Amazon Web Services,Jwt,Aws Cognito,我使用的是aws cognito用户池,在用户登录后,我在单页应用程序中获得了一个id令牌,这是预期的,然后对于每个请求,我需要在我的后端rest API中验证id令牌,它是java的,aws文档没有太多提到如何做 有什么例子吗 混淆包括: id令牌似乎不仅仅是一个签名的JWT,它也是加密的,当使用nimbus库时,我需要为加密的JWT指定一个秘密,我在哪里可以获得这个秘密?我的理解是这应该来自aws,我是否需要下载一些东西然后放入jvm密钥库 有一个著名的jwts.json可以从aws下载,它
您可以使用标准验证令牌。此外,验证JWT令牌还涉及几个步骤。虽然我找不到Java示例,但下面是一个NodeJS示例,它将解释验证过程
const jwt = require('jsonwebtoken');
const jwtToken = "sampletoken****";
const jwkPem = { "alg" : "RS256", "kid" : "samplekid****" }
var decodedJwt = jwt.decode(jwtToken, {complete: true});
//Fail if the token is not jwt
if (!decodedJwt) {
console.log("Not a valid JWT token");
return;
}
//Fail if token is not from your User Pool
if (decodedJwt.payload.iss != iss) {
console.log("invalid issuer");
return;
}
//Reject the jwt if it's not an 'Access Token'
if (!(decodedJwt.payload.token_use == 'id' ||
decodedJwt.payload.token_use == 'access')) {
console.log("token_use is invalid");
return;
}
//Get the kid from the token and retrieve corresponding PEM
var kid = decodedJwt.header.kid;
var pem = jwkPem[kid];
if (!pem) {
console.log("Invalid access token");
return;
}
//Verify the signature of the JWT token to ensure it's really coming from your User Pool and that it has not expired
jwt.verify(jwtToken, pem, { issuer: iss, maxAge: 3600000}, function(err, payload) {
if(err) {
console.log(err);
} else {
console.log("Authorization successful");
}
});
至于这个秘密,你指的是特定于应用程序客户端的吗?这是您在创建和安装应用程序客户端时得到的。转到AWS控制台和Cognito。选择适当的用户池,单击应用程序客户端。这是一个秘密,但你必须确保在创建应用程序客户端时选择创建它的选项(或者不使用)。否则,就做一个新的。我只是挣扎着想和大家分享一下 如果使用maven,请将其添加到pom.xml中
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
<version>0.4.0</version>
</dependency>
创建一个实现RSAKeyProvider的类
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.JwkProviderBuilder;
import com.auth0.jwt.interfaces.RSAKeyProvider;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
public class AwsCognitoRSAKeyProvider implements RSAKeyProvider {
private final URL aws_kid_store_url;
private final JwkProvider provider;
public AwsCognitoRSAKeyProvider(String aws_cognito_region, String aws_user_pools_id) {
String url = String.format("https://cognito-idp.%s.amazonaws.com/%s/.well-known/jwks.json", aws_cognito_region, aws_user_pools_id);
try {
aws_kid_store_url = new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException(String.format("Invalid URL provided, URL=%s", url));
}
provider = new JwkProviderBuilder(aws_kid_store_url).build();
}
@Override
public RSAPublicKey getPublicKeyById(String kid) {
try {
return (RSAPublicKey) provider.get(kid).getPublicKey();
} catch (JwkException e) {
throw new RuntimeException(String.format("Failed to get JWT kid=%s from aws_kid_store_url=%s", kid, aws_kid_store_url));
}
}
@Override
public RSAPrivateKey getPrivateKey() {
return null;
}
@Override
public String getPrivateKeyId() {
return null;
}
}
现在,您可以通过以下方式验证您的令牌
String aws_cognito_region = "us-east-1"; // Replace this with your aws cognito region
String aws_user_pools_id = "us-east-1_7DEw1nt5r"; // Replace this with your aws user pools id
RSAKeyProvider keyProvider = new AwsCognitoRSAKeyProvider(aws_cognito_region, aws_user_pools_id);
Algorithm algorithm = Algorithm.RSA256(keyProvider);
JWTVerifier jwtVerifier = JWT.require(algorithm)
//.withAudience("2qm9sgg2kh21masuas88vjc9se") // Validate your apps audience if needed
.build();
String token = "eyJraWQiOiJjdE.eyJzdWIiOiI5NTMxN2E.VX819z1A1rJij2"; // Replace this with your JWT token
jwtVerifier.verify(token);
请注意,JwkProviderBuilder将构建一个带有LRU缓存的JwkProvider,该缓存缓存从aws密钥存储库中检索到的密钥,非常整洁!可以使用生成器更改缓存规则
[UPDATE]将创建JwkProvider移动到构造函数,因此正如@danieln所评论的那样,缓存也得到了尊重,然而,它是旧的,有几个不推荐的项目,它会给你一个ideahttps://aws.amazon.com/blogs/developer/building-a-serverless-developer-authentication-api-in-java-using-aws-lambda-amazon-dynamodb-and-amazon-cognito-part-2/ 或者在这里看到这篇非常精彩的相关文章,我花了几个小时试图从不同的角度实现这一点。到目前为止,我发现没有一个解决方案像这一个那么简单直接。工作起来很有魅力!非常感谢,伙计。非常感谢,我终于成功了。我必须做的两件小事是获取jwt库的更新版本,并确保jwt令牌已被删除。@AndiDev回答得很好!您不应该初始化JwkProvider一次,然后在getPublicKeyById中返回它,而不是反复初始化它吗?@danieln说得不错。感觉应该在构造函数中创建JwkProvider提供程序。否则,我想缓存就不起作用了。不再使用此代码,因此我无法验证它。如果你能验证它是否按预期工作,我可以更改答案。我验证了它,它按预期工作。
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.JwkProviderBuilder;
import com.auth0.jwt.interfaces.RSAKeyProvider;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
public class AwsCognitoRSAKeyProvider implements RSAKeyProvider {
private final URL aws_kid_store_url;
private final JwkProvider provider;
public AwsCognitoRSAKeyProvider(String aws_cognito_region, String aws_user_pools_id) {
String url = String.format("https://cognito-idp.%s.amazonaws.com/%s/.well-known/jwks.json", aws_cognito_region, aws_user_pools_id);
try {
aws_kid_store_url = new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException(String.format("Invalid URL provided, URL=%s", url));
}
provider = new JwkProviderBuilder(aws_kid_store_url).build();
}
@Override
public RSAPublicKey getPublicKeyById(String kid) {
try {
return (RSAPublicKey) provider.get(kid).getPublicKey();
} catch (JwkException e) {
throw new RuntimeException(String.format("Failed to get JWT kid=%s from aws_kid_store_url=%s", kid, aws_kid_store_url));
}
}
@Override
public RSAPrivateKey getPrivateKey() {
return null;
}
@Override
public String getPrivateKeyId() {
return null;
}
}
String aws_cognito_region = "us-east-1"; // Replace this with your aws cognito region
String aws_user_pools_id = "us-east-1_7DEw1nt5r"; // Replace this with your aws user pools id
RSAKeyProvider keyProvider = new AwsCognitoRSAKeyProvider(aws_cognito_region, aws_user_pools_id);
Algorithm algorithm = Algorithm.RSA256(keyProvider);
JWTVerifier jwtVerifier = JWT.require(algorithm)
//.withAudience("2qm9sgg2kh21masuas88vjc9se") // Validate your apps audience if needed
.build();
String token = "eyJraWQiOiJjdE.eyJzdWIiOiI5NTMxN2E.VX819z1A1rJij2"; // Replace this with your JWT token
jwtVerifier.verify(token);