メインコンテンツまでスキップ

Java用SDKからCognito User Poolsを使用する

· 約4分
moritalous
お知らせ

過去にQiitaに投稿した内容のアーカイブです。

ブラウザからのユーザーアクセスであればamazon-cognito-identity-jsを使ってユーザーの追加、ログインは簡単にできますが、どうにかサーバーサイドでできないものか、調査しました。 Javaのプログラムからユーザー追加やログイン(トークンの取得)ができましたので紹介します。

前準備(マネジメントコンソール)

ユーザープールを作成します。ユーザーの登録以降のフローは異なりますが、ユーザープールを作成する手順まではこちらのサイトが参考になると思います。

前準備(Java)

AWS SDKを使う設定をします。Gradleの場合は、build.gradleに以下の内容を追加します。

build.gradle
    // https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-cognitoidp
compile group: 'com.amazonaws', name: 'aws-java-sdk-cognitoidp', version: '1.11.123'

AWSCognitoIdentityProviderの作成

AWSCredentialsProviderとリージョン(今回は東京リージョン)を引数に渡して、AWSCognitoIdentityProviderを作成します。

AWSCredentialsProviderの作成方法は色々あるようですが、今回はこちらを参考にProfileCredentialsProviderを使用しました。

AWSCredentialsProvider credentialsProvider = new ProfileCredentialsProvider("プロファイル名");

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

ユーザーの新規作成

ユーザーを新規作成します。 ユーザープールIDはマネジメントコンソールで確認できます。

AdminCreateUserRequest adminCreateUserRequest = new AdminCreateUserRequest();
adminCreateUserRequest
.withUserPoolId("ユーザープールID")
.withUsername("新規作成するユーザーのユーザー名")
.withTemporaryPassword("新規作成するユーザーの一時パスワード");
AdminCreateUserResult response = client.adminCreateUser(adminCreateUserRequest);

トークンの取得

ユーザーIDとパスワードを使ってトークンを取得します。クライアントIDはマネジメントコンソール上の「Apps」のところにあります。 ※Appsの設定のEnable sign-in API for server-based authentication (ADMIN_NO_SRP_AUTH)は有効になっている必要があります。

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

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

AdminInitiateAuthResult response = client.adminInitiateAuth(request);

成功するとトークンが取得できます。(加工しています)

System.out.println(response.getAuthenticationResult().toString());
トークン取得成功時
{
AccessToken: xxxxx,
ExpiresIn: 3600,
TokenType: Bearer,
RefreshToken: yyyyy,
IdToken: zzzzz,
}

ただし、新規作成したばかりのユーザーは、パスワード変更の必要があるため、トークンは取得できません。その場合、ChallengeNameが「NEW_PASSWORD_REQUIRED」となってしまいますので、次の一時パスワード変更を行います。 (トークン取得成功時はChallengeNameがnull、トークン取得失敗時はAuthenticationResultがnullになるようです)

System.out.println(response.getChallengeName());
トークン取得失敗時
NEW_PASSWORD_REQUIRED

一時パスワード変更

一時パスワード変更処理です。adminInitiateAuthのレスポンスで受け取るChallengeNameとSessionが必要になります。

Map<String, String> challengeResponses = new HashMap<>();
challengeResponses.put("USERNAME", "ユーザー名");
challengeResponses.put("NEW_PASSWORD", "変更後の新しいパスワード");

AdminRespondToAuthChallengeRequest request = new AdminRespondToAuthChallengeRequest();
request
.withChallengeName(adminInitiateAuthResult.getChallengeName())
.withUserPoolId("ユーザープールID")
.withClientId("クライアントID")
.withSession(adminInitiateAuthResult.getSession())
.withChallengeResponses(challengeResponses);

AdminRespondToAuthChallengeResult response = client.adminRespondToAuthChallenge(request);

上手く行けば、この手順を持ってトークンが取得できます。

System.out.println(response.getAuthenticationResult().toString());
{
AccessToken: xxxxx,
ExpiresIn: 3600,
TokenType: Bearer,
RefreshToken: yyyyy,
IdToken: zzzzz,
}

トークンの更新

リフレッシュトークンを使用してのトークンの更新は、トークンの取得と同様adminInitiateAuthメソッドにて行います。 authParametersの値とAuthFlowが違うだけです

Map<String, String> authParameters = new HashMap<>();
authParameters.put("REFRESH_TOKEN", "リフレッシュトークン");

AdminInitiateAuthRequest request = new AdminInitiateAuthRequest();
request
.withAuthFlow(AuthFlowType.REFRESH_TOKEN_AUTH)
.withUserPoolId("ユーザープールID")
.withClientId("クライアントID")
.withAuthParameters(authParameters);

AdminInitiateAuthResult response = client.adminInitiateAuth(request);

取得したトークンの利用方法など

勉強中です。