[アップデート]Cognitoがリフレッシュトークンの個別失効に対応しました!

2021.06.11

Cognitoユーザープールがリフレッシュトークンの個別失効に対応しました!

今までもグローバルサインアウトをすることで発行したすべてのリフレッシュトークンを無効にすることはできました。

今回新しく追加された機能では、リフレッシュトークンを個別に無効化できます。 たとえば、ユーザーが新しいデバイスでサインインした際に、以前のデバイスでのサインインに関連するリフレッシュトークンを無効にするといったようなことができます。

さっそく試してみました!

今までのリフレッシュトークン無効化をやってみる

まずはこの辺のブログを参考にして、Cognitoユーザープールの環境を構築します。 合わせて、ユーザーのサインアップもしておきます。

次に aws cognito-idp admin-initiate-auth コマンドでCognitoのサインインを試します。

$ USER_POOL_ID=us-west-2_xxxxxxxxx
$ CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxx
$ USER_EMAIL="email@example.com"
$ PASSWORD="Password01@"
$ aws cognito-idp admin-initiate-auth \
  --user-pool-id ${USER_POOL_ID} \
  --client-id ${CLIENT_ID} \
  --auth-flow ADMIN_NO_SRP_AUTH \
  --auth-parameters "USERNAME=${USER_EMAIL},PASSWORD=${PASSWORD}"

サインインすると、こんな形で アクセストークンリフレッシュトークンIDトークン が返ってきます。

今回、 リフレッシュトークン を利用した検証をしたいので、 --query を使ってリフレッシュトークンだけ取り出します。

$ REFRESH_TOKEN=$(aws cognito-idp admin-initiate-auth \
  --user-pool-id ${USER_POOL_ID} \
  --client-id ${CLIENT_ID} \
  --auth-flow ADMIN_NO_SRP_AUTH \
  --auth-parameters "USERNAME=${USER_EMAIL},PASSWORD=${PASSWORD}" \
  --query "AuthenticationResult.RefreshToken" \
  --output text) && echo ${REFRESH_TOKEN}

リフレッシュトークンを使って、 IDトークンアクセストークン を再発行したい場合も、 次のように aws cognito-idp admin-initiate-auth コマンドを使用します。

$ aws cognito-idp admin-initiate-auth \
  --user-pool-id ${COGNITO_USER_POOL_ID} \
  --client-id ${COGNITO_CLIENT_ID} \
  --auth-flow REFRESH_TOKEN_AUTH \
  --auth-parameters "REFRESH_TOKEN=${REFRESH_TOKEN}"

リフレッシュトークンが有効である場合、こんな形で再発行された アクセストークンIDトークン が返ってきます。

このリフレッシュトークンを無効にしたい場合、 今までは aws cognito-idp admin-user-global-sign-out コマンドを利用して、そのユーザーに関連するリフレッシュトークンをすべて無効にしていました。

たとえば、次のコマンドで無効化できます。

$ aws cognito-idp admin-user-global-sign-out \
  --user-pool-id ${USER_POOL_ID} \
  --username ${USER_EMAIL}

このコマンドを実行した後、再度リフレッシュトークンからIDトークンを再発行しようとすると、次のようにエラーが発生してリフレッシュトークンが無効化されていることがわかります。

$ aws cognito-idp admin-initiate-auth \
  --user-pool-id ${USER_POOL_ID} \
  --client-id ${CLIENT_ID} \
  --auth-flow REFRESH_TOKEN_AUTH \
  --auth-parameters "REFRESH_TOKEN=${REFRESH_TOKEN}"

An error occurred (NotAuthorizedException) when calling the AdminInitiateAuth operation: Refresh Token has been revoked

追加された個別リフレッシュトークン無効化をやってみる

個別リフレッシュトークン無効化のために、新しく aws cognito-idp revoke-token コマンドが追加されています。

AWS CLIで試す場合は、AWS CLIのバージョンが古いとコマンド自体が存在しないので、最新バージョンにしてください。

$ aws --version

aws-cli/2.2.11 Python/3.8.8 Darwin/20.5.0 exe/x86_64 prompt/off

また、個別にリフレッシュトークンを無効化したい場合は、マネジメントコンソールの、全般設定 > アプリクライアントを選び、高度なトークン設定から トークンの取り消しを有効化 にチェックを入れてください。

その後、同様にリフレッシュトークンを2つ取得します。

$ USER_POOL_ID=us-west-2_xxxxxxxxx
$ CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxx
$ USER_EMAIL="email@example.com"
$ PASSWORD="Password01@"
$ REFRESH_TOKEN=$(aws cognito-idp admin-initiate-auth \
  --user-pool-id ${USER_POOL_ID} \
  --client-id ${CLIENT_ID} \
  --auth-flow ADMIN_NO_SRP_AUTH \
  --auth-parameters "USERNAME=${USER_EMAIL},PASSWORD=${PASSWORD}" \
  --query "AuthenticationResult.RefreshToken" \
  --output text) && echo ${REFRESH_TOKEN}

取得した2つのリフレッシュトークンのうち、1つのリフレッシュトークンを無効化してみます。

次のように、 aws cognito-idp revoke-token コマンドを実行すると無効化できます。

$ aws cognito-idp revoke-token \
  --client-id ${CLIENT_ID} \
  --token ${REFRESH_TOKEN}

このコマンドを実行した後、リフレッシュトークンからIDトークンを再発行しようとすると、次のようにエラーが発生してたしかに無効化されていることがわかります。

$ aws cognito-idp admin-initiate-auth \
  --user-pool-id ${USER_POOL_ID} \
  --client-id ${CLIENT_ID} \
  --auth-flow REFRESH_TOKEN_AUTH \
  --auth-parameters "REFRESH_TOKEN=${REFRESH_TOKEN}"

An error occurred (NotAuthorizedException) when calling the AdminInitiateAuth operation: Refresh Token has been revoked

無効化していないもう1つのリフレッシュトークンを利用して同様にリフレッシュトークンからIDトークンを再発行しようとすると、問題なくIDトークンが再発行できます。 リフレッシュトークンが個別に無効化できていることがわかります。

終わりに

今回のアップデートでCognitoユーザープールのリフレッシュトークンがより細かく制御できるようになりました。

これを機会にぜひCognitoユーザープールを利用した認証も試してみてください。