Amplifyで、STSの認証を直接行う


Amazon CognitoのIDプールを使って外部プロバイダーがウェブベースの認証を提供する場合に、Cognitoが発行する認証の有効期限を伸ばすことがそのままでは難しかったので、その調査の記録を書いておきます。

そもそもの認証フロー

開発者認証or外部プロバイダーどちらを使ったとしても、Amplifyの認証を素直に使うと下の拡張認証フローになります。

引用元:
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/authentication-flow.html

この図を見てもらうとわかるのですが、最終的な認証情報はAWS STSから渡ってきます。そして、AWS STSでは認証情報を発行する際にその有効期限を指定することができます。しかし、拡張認証フローだとAmazon CognitoがAWS STSとやり取りしてしまうため、有効期限を指定することが出来ず、デフォルトの有効期限(3600秒)が指定されてします。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity

そこで、先程のページに有る、基本的な認証フローを使うことになります。

引用元: https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/authentication-flow.html

見ての通り、AWS STSへ直接アクセスすることが出来ます。

実際のやり方

AmplifyでのCognito認証はすでに済んでいるものとし、AWS STSの認証に必要な下記のパラメータはすべて準備出来ているものとします。

  • (A) sts:AssumeRoleWithWebIdentityアクションが実行可能なIAM Role(そしてそのARN)
  • (B) 64字以下のセッション名として使う任意の文字列
  • (C) GetOpenIdToken...で発行されたトークン

上記がそろえば、あとはさっくりAWS SDKのAPIを叩くだけです。

const stsParams = {
  DurationSeconds:  900, // 最小900秒(15分)〜最大43200秒(12時間)まで設定することが出来ます。
  RoleArn:          `(A)の値`,
  RoleSessionName:  `(B)の値`,
  WebIdentityToken: `(C)の値`,
};
const sts = new AWS.STS();
const stsResponse = await sts.assumeRoleWithWebIdentity(stsParams).promise();
AWS.config.update({
  credentials: new AWS.Credentials({
    accessKeyId:     stsResponse.Credentials.AccessKeyId,
    secretAccessKey: stsResponse.Credentials.SecretAccessKey,
    sessionToken:    stsResponse.Credentials.SessionToken,
 }),
});

Amplifyの認証設定はいっさいやらないんかい!って感じですが、Amplifyのコードを見る限り、Credentialsクラスなどから認証情報を設定する方法はなさそうです。AWSのグローバルの認証情報を更新しておくと、Amplifyのもろもろはそれを見て勝手に認証してくれるようなので、この書き方に落ち着きました。

  • ※ Amplifyのバージョンによって、aws-sdkのバージョンが違ってくるので、この書き方はできない場合があります。
  • ※ この書き方はaws-sdk v2系を想定しています。
  • ※サーバー側のAPIを用意できるなら、CognitoのEPをそのままモックしてしまうほうが良いです。