在 Java 上验证 AWS id 令牌
Verify AWS id Token on Java
我在亚马逊中使用 Cognito 来验证我的移动用户,一旦他们完成登录,Cognito 就会提供一组令牌,我在后端使用 id 令牌。我已按照在您的 Web API 中使用 ID 令牌和访问令牌部分中的步骤进行操作
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html 我卡在第 6 步了。
据我所知,我从 Amazon 获取字符串中的模数和指数,我必须用它们构建一个 PublicKey,以验证 JWT 签名。
我不知道如何使用字符串中的这两个参数构建公钥。
我终于找到了解决方法,aws 论坛中有一个示例 https://forums.aws.amazon.com/message.jspa?messageID=728870 但代码是在 Kotlin 中。我只是将它移植到 java 并进行了一些测试,我最终验证了我的 JWT 签名:
byte[] decodedModulus = Base64.getUrlDecoder().decode(yourModulus);
byte[] decodedExponent = Base64.getUrlDecoder().decode(yourExponent);
BigInteger modulus = new BigInteger(1, decodedModulus);
BigInteger exponent = new BigInteger(1, decodedExponent);
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFactory;
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
Boolean verify = parsedToken.verify(verifier);}
希望对遇到同样问题的人有所帮助。
我编程的方式是这样的,
// 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;
我在亚马逊中使用 Cognito 来验证我的移动用户,一旦他们完成登录,Cognito 就会提供一组令牌,我在后端使用 id 令牌。我已按照在您的 Web API 中使用 ID 令牌和访问令牌部分中的步骤进行操作 https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html 我卡在第 6 步了。
据我所知,我从 Amazon 获取字符串中的模数和指数,我必须用它们构建一个 PublicKey,以验证 JWT 签名。
我不知道如何使用字符串中的这两个参数构建公钥。
我终于找到了解决方法,aws 论坛中有一个示例 https://forums.aws.amazon.com/message.jspa?messageID=728870 但代码是在 Kotlin 中。我只是将它移植到 java 并进行了一些测试,我最终验证了我的 JWT 签名:
byte[] decodedModulus = Base64.getUrlDecoder().decode(yourModulus);
byte[] decodedExponent = Base64.getUrlDecoder().decode(yourExponent);
BigInteger modulus = new BigInteger(1, decodedModulus);
BigInteger exponent = new BigInteger(1, decodedExponent);
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFactory;
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
Boolean verify = parsedToken.verify(verifier);}
希望对遇到同样问题的人有所帮助。
我编程的方式是这样的,
// 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;