Aws cognitoユーザープールを使用しています。ユーザーがサインインした後、シングルページアプリケーションでIDトークンを取得しました。これは予期されていることです。その後、リクエストごとに、JavaのバックエンドRESTAPIでIDトークンを確認する必要があります。 、awsdocはそれを行う方法についてあまり言及していませんでした。
その例はありますか?
混乱は次のとおりです。
idトークンは署名されたJWTだけでなく、暗号化されているようです。ニンバスライブラリを使用する場合、暗号化されたJWTのシークレットを指定する必要があります。シークレットはどこで入手できますか?私の理解では、これはawsから取得する必要があります。何かをダウンロードしてから、jvmキーストアに配置する必要がありますか?
よく知られているjwts.jsonがawsからダウンロードできます。次のようになります。
`
{
"keys": [
{
"alg": "RS256",
"e": "AQAB",
"kid": "HFPWHdsrG5WyulOwH5dai69YTsWz2KBB1NHbAcVx7M0=",
"kty": "RSA",
"n": "...",
"use": "sig"
},
{
"alg": "RS256",
"e": "AQAB",
"kid": "kSwTdVq/qD4Ra4Q8dJqUTlvOA7eiLxezOZ3mJKI61zU=",
"kty": "RSA",
"n": "....",
"use": "sig"
}
]
}
`
これを理解する方法、各プロパティは何に使用されますか?ユーザープール内のすべてのユーザーが1つのキーを表すということですか?
私はこれに苦労し、それを共有しようと思いました。
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>
Gradleを使用する場合は、
compile 'com.auth0:jwks-rsa:0.4.0'
compile 'com.auth0:Java-jwt:3.3.0'
RSAKeyProviderを実装するクラスを作成します
import com.auth0.jwk.Jwk;
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;
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 {
this.aws_kid_store_url = new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException(String.format("Invalid URL provided, URL=%s", url));
}
}
@Override
public RSAPublicKey getPublicKeyById(String kid) {
try {
JwkProvider provider = new JwkProviderBuilder(aws_kid_store_url).build();
Jwk jwk = provider.get(kid);
return (RSAPublicKey) jwk.getPublicKey();
} catch (Exception 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は、awsキーストアから取得したキーをキャッシュするLRUキャッシュを備えたJwkProviderを構築することに注意してください。これは非常に優れています。キャッシュルールはビルダーで変更できます。
秘密については、App Client固有のものを参照していますか?これは、AppClientを作成するときに取得します。 AWSコンソールとCognitoに移動します。適切なユーザープールを選択し、[アプリクライアント]をクリックします。秘密はありますが、App Clientを作成するときに、作成するオプションを選択する(または使用しない)ようにする必要があります。それ以外の場合は、新しいものを作成します。
標準の JWTライブラリ を使用してトークンを検証できます。さらに、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");
}
});