技術系TIPS
PR

【Java版】AWSのSDKを使ってCognito認証を実現する

saratogax
記事内に商品プロモーションを含む場合があります

AWS で運用している API サービスに対して、特定のクライアントからのアクセスを許可したい。

こんな時、AWS Cognito を利用すれば、利用者ごとに一意な ID を割り振ることができます。

今回は既に Cognito で以下が設定されている前提で、Java 版の AWS SDK を使って認証を通してみましょう。

・ユーザプール
・ユーザ
・アプリクライアント
・クレデンシャル(IAM)

今回のケースでは、ユーザプールから取得した ID トークンをリクエストヘッダの Authorization に Bearer で指定させ、AWS の Web サービスとの認証が可能にすることを目的としています。

利用するライブラリ

AWS SDK の中から Cognito に特化したライブラリを利用してみましょう。

com.amazonaws:aws-java-sdk-cognitoidp

以下が SDK の Maven リポジトリ。

以下が SDK の GitHub になります。

2022 年 3 月時点での最新バージョンは 1.12.x になります。

Kotlin DSL の gradle の場合は以下のように定義すれば問題ありません。

implementation("com.amazonaws:aws-java-sdk-cognitoidp:1.12.180")

AWSCognitoIdentityProviderの取得

まずは AWS のクレデンシャルを使って、AWSCognitoIdentityProvider オブジェクトの作成をしてみましょう。

クレデンシャルはプロファイル(aws configure で生成した profile)でもいいですし、以下のキー値を直接指定することもできます。

・AWS_ACCESS_KEY_ID
・AWS_SECRET_ACCESS_KEY

プロファイルを使う

プロファイルを使う場合は、ProfileCredentialsProvider の引数にプロファイル名を指定します。

AWSCredentialsProvider credentialsProvider = new ProfileCredentialsProvider("profileName");

AWSCognitoIdentityProvider cognitoIdentityProvider = AWSCognitoIdentityProviderClientBuilder.standard()
    .withCredentials(credentialsProvider)
    .withRegion(Regions.AP_NORTHEAST_1)
    .build();

キー値を使う

「AWS_ACCESS_KEY_ID」と「AWS_SECRET_ACCESS_KEY」を使う場合は BasicAWSCredentials を利用します。

これで AWSCredentials オブジェクトが生成されるので、AWSStaticCredentialsProvider を利用して AWSCredentialsProvider を作ります。

AWSCredentials credentials = new BasicAWSCredentials("AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY");

AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);

AWSCognitoIdentityProvider cognitoIdentityProvider = AWSCognitoIdentityProviderClientBuilder.standard()
    .withCredentials(credentialsProvider)
    .withRegion(Regions.AP_NORTHEAST_1)
    .build();

AWS のアカウントで STS を利用した一時認証を使っている場合はセッショントークンの指定も必要になるので注意が必要です。詳しくは AWS のドキュメントを参照してください。

セッショントークンを利用する場合は BasicAWSCredentials ではなく BasicSessionCredentials になります。

AWSCredentials credentials = new BasicSessionCredentials("AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN");

AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);

AWSCognitoIdentityProvider cognitoIdentityProvider = AWSCognitoIdentityProviderClientBuilder.standard()
    .withCredentials(credentialsProvider)
    .withRegion(Regions.AP_NORTHEAST_1)
    .build();

AssumeRoleを使う

いやいや、IAM ロールを使って Assume Role を利用したいという場面もありますよね。

AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest()
    .withRoleArn("IAMロールのARN")
    .withRoleSessionName("任意の文字列");

AWSCredentialsProvider credentialsProvider = new InstanceProfileCredentialsProvider(true);

AWSSecurityTokenService sts = AWSSecurityTokenServiceClientBuilder
    .standard()
    .withCredentials(credentialsProvider)
    .withRegion(Regions.AP_NORTHEAST_1)
    .build();

AssumeRoleResult assumeRoleResult = sts.assumeRole(assumeRoleRequest);
Credentials credentials = assumeRoleResult.getCredentials();

credentials に以下の情報が入っているので、

・AWS_ACCESS_KEY_ID
・AWS_SECRET_ACCESS_KEY
・AWS_SESSION_TOKEN

あとは上で書いた BasicSessionCredentials を利用すれば OK です。

AWSCredentials credentials = new BasicSessionCredentials(
    credentials.getAccessKeyId(),
    credentials.getSecretAccessKey(),
    credentials.getSessionToken()
);

AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);

AWSCognitoIdentityProvider cognitoIdentityProvider = AWSCognitoIdentityProviderClientBuilder.standard()
    .withCredentials(credentialsProvider)
    .withRegion(Regions.AP_NORTHEAST_1)
    .build();

AssumeRole を利用する場合は、別途「aws-java-sdk-sts」のライブラリが必要になります。

IDトークンを取得する

冒頭でも書きましたが、既に Cognito のユーザプールやユーザは作成されているとします。

ID トークンの取得に必要は情報は以下の通り。

・ユーザ名
・パスワード
・ユーザプールID
・クライアントID

先ほど取得した AWSCognitoIdentityProvider(cognitoIdentityProvider)と上記の情報を合わせて認証してみましょう。

Map<String, String> authParam = new HashMap<>();
authParam.put("USERNAME", "ユーザ名");
authParam.put("PASSWORD", "パスワード");

AdminInitiateAuthRequest request = new AdminInitiateAuthRequest();

request
    .withAuthFlow(AuthFlowType.ADMIN_NO_SRP_AUTH)
    .withUserPoolId("ユーザプールID")
    .withClientId("クライアントID")
    .withAuthParameters(authParam);

AdminInitiateAuthResult authResult = cognitoIdentityProvider.adminInitiateAuth(request);

ID トークンは以下のように取得できます。

authResult.getAuthenticationResult().getIdToken()

まとめ

AWS の Java SDK を使って、Cognito の認証を行ってみました。

必要な情報が揃っていれば、それほど大変な作業ではありませんね。

ちなみに ID トークンは JWT(JSON Web Token)形式となっています。

さらにヘッダ部分やペイロード部分を検証してあげることで、トークンが意図したものかどうか確認ができます。

あわせて読みたい
【Java版】CognitoのIDトークンのJWT検証とダミートークンの作成
【Java版】CognitoのIDトークンのJWT検証とダミートークンの作成
ABOUT ME
saratoga
saratoga
フリーランスエンジニア
仕事にも趣味にも IT を駆使するフリーランスエンジニア。技術的な TIPS や日々の生活の中で深堀りしてみたくなったことを備忘録として残していきます。
記事URLをコピーしました