【AWS】AWS Cognito IDプール(フェデレーティッド ID)を用いてAWSの一時「Credentials Key」を発行する方法

背景

  • AWS Cognitoはユーザーの認証と認可を処理できるサービスです。
  • AWS Cognitoを使用すれば、ユーザーのデータベースをAWS RDSなどのAWSの別サービスで作成することなく、ユーザーのサインアップやサインイン機能を実装することができます。
  • アカウントのデータ管理などがAWS側になるフルマネージドサービスなので、セキュリティ的にも自社でユーザーのデータベースを持つより安心かと思います。
  • AWS CognitoにはAmazon Cognito ID プール (フェデレーティッド ID)という機能があります。
  • この機能を利用すれば、AWSの一時「Credentials Key」を発行することができので、一定時間だけ使用できるIAMユーザー(ロール)のようなものをこの機能で実現することができます。
  • この機能を使用すれば、例えば、s3へデータをupするWEBアプリの実装などが簡単にできます。

目標

ユーザープールとIDプール(フェデレーティッド ID)について

リソース名 機能 個人的なイメージ
ユーザープール 認証を行う ユーザー情報を保存するデータベース
IDプール(フェデレーティッド ID) 認可を行う AWSのIAM関連の許認可を与えてくれるリソース
  • それぞれのリソースの機能と個人的なイメージを上記の通り表にまとめました。
  • ユーザープールはユーザーの認証を行うリソースで、ユーザーのサインインやログアウトに使用されるリソースです。
  • そして、IDプール(フェデレーティッド ID)は「AWS Credentials」を発行する認可機能を担っています。
  • IDプール(フェデレーティッド ID)は外部プロバイダ(GoogleやAppleなどのログイン機能と連携できるらしい)との接続も可能の模様です。
  • IDプール(フェデレーティッド ID)をユーザープールと連携させて使用する場合の流れは以下のようなイメージです。
    1. ユーザープールで登録されたユーザーにログインする。
    2. ログインした際に取得できるtokenをIDプール(フェデレーティッド ID)に送る。
    3. IDプール(フェデレーティッド ID)が一時「AWS Credentials Key」を発行する。
    4. 発行された「AWS Credentials Key」を使用してAWSリソースにアクセスして各種操作を行う。
  • 上記の通り、IDプール(フェデレーティッド ID)を使用して「AWS Credentials Key」を発行するには何かしらのユーザーの認証機能が必要となります。
  • この記事では、ユーザープールを認証機能として使用し、「AWS Credentials Key」を発行する方法を説明します。

ユーザープールの作成方法

  • まずは、IDプール(フェデレーティッド ID)と連携させるユーザープールをAWSのコンソールで作成します。

「ユーザープール」に移動します。

02_0048.png

「ユーザープールを作成」をクリックします。

03_0048.png

「サインインエクスペリエンス」の設定を行います。

  • 今回は「Eメール」でのサインインを行うので、「Eメール」をチェックし、「次へ」をクリックします。
    04_0048.png

「セキュリティ要件」の設定を行います。

  • 今回は「MFAなし」でテストを行うので「MFAなし」を選択し、「次へ」をクリックします。
  • セキュリティを強化したい場合などは適宜「パスワードポリシー」などを変更して下さい。
    05_0048.png

「サインアップエクスペリエンス」の設定を行います。

  • 「サインアップエクスペリエンス」はデフォルトのままの設定で良いので、そのまま「次へ」をクリックします。
    06_0048.png

「メッセージ配信」の設定を行います。

  • 「Eメールプロバイダー」を「CognitoでEメールを送信」に変更し、「次へ」をクリックします。
    (おそらく「Amazon SES」を使用する場合は、SES側で何か設定が必要そうだからです。)
    07_0048.png

「アプリケーションを統合」の設定を行います。

  1. 「ユーザープール名」を入力します。
    ここでは、「dev_user_pool_01」とします。
  2. 「アプリケーションクライアント名」を入力します。
    ここでは、「dev_user_app_client_01」とします。
  3. 「高度なアプリケーションクライアントの設定」の折りたたみを開きます。
  4. 「認証フロー」のプルダウンから「ALLOW_ADMIN_USER_PASSWORD_AUTH」を選択し「認証フロー」として追加します。
    なお、「ALLOW_ADMIN_USER_PASSWORD_AUTH」の旧名は「ADMIN_NO_SRP_AUTH」です。

    【引用:ユーザープール認証フロー
    ・CreateUserPoolClient または UpdateUserPoolClient を呼び出すときは、ExplicitAuthFlow パラメータに ALLOW_ADMIN_USER_PASSWORD_AUTH (以前は ADMIN_NO_SRP_AUTH と呼ばれています) を含めます。

  5. 「次へ」をクリックします。
    08_0048.png

全ての設定を確認し、ユーザープールを作成します。

  • 最後に、全ての設定に間違いがないか確認する画面が出ます。
  • 問題なければ「ユーザープールを作成」をクリックし、ユーザープールを作成します。
    09_0048.png

ユーザープールが作成されたことを確認します。

  • ユーザープールが正常に作成されるとユーザープールのトップ画面に作成したユーザープール名が表示されます。
    10_0048.png

IDプール(フェデレーティッド ID)の作成方法

  • ユーザープールが作成できたので、次にIDプール(フェデレーティッド ID)を作成していきます。
  • IDプール(フェデレーティッド ID)の作成には、ユーザープールの「ユーザープールID」と「アプリクラインアントID」が必要になるので、事前にそれを確認して控えておきます。
  • IDプール(フェデレーティッド ID)はクリックするとUIが古いAWSコンソールの画面になります。
  • おそらくは、まだデザインが対応していないのかと思われますが、非常に使用しずらい(フェデレーティッド IDに(IDプール)とついていないのも記事を読んだ際に混乱するし、、、)UIなので、早く新しいデザインに対応して欲しいところです。。。

「フェデレーティッドID」の作成に必要な「ユーザープールID」を控えます。

  • 「ユーザープールID」を控えたら、「ユーザープール名」をクリックしてユーザプールの詳細画面に移動します。
    11_0048.png

「フェデレーティッドID」の作成に必要な「アプリクラインアントID」を控えます。

  • 以下の手順で、「アプリクラインアントID」が記載されている画面に遷移し、「アプリクラインアントID」を控えます。
    12_0048.png
    13_0048.png

「フェデレーティッドID」に移動します。

14_0048.png

「フェデレーティッドID」を作成します。

  1. 「IDプール名」を入力します。
    ここでは、「dev_id_pool_01」とします。
  2. 先ほど控えておいた「ユーザープールID」と「アプリクライアントID」を入力します。
  3. 「プールの作成」をクリックし、IDプール(フェデレーティッド ID)を作成します。
    15_0048.png

「フェデレーティッドID」に付与するIAMロールを作成しアタッチします。

  • ユーザープールで認証され、IDプール(フェデレーティッド ID)で認可されたユーザーに付与するIAMロールを作成し、アタッチします。

  • 認証されていない場合にもIAMロールを渡すことができるので、ここでは

    1. 認証されていない時に使用されるロール
    2. 認証された時に使用されるロール

    の2つのIAMロールが作成されています。
    16_0048.png

ユーザープールにユーザーをAWS CLIで登録する方法

  • コンソールでユーザープールとIDプール(フェデレーティッド ID)の作成が完了しました。

  • 次に、ログインに使用するアカウントをユーザプールに新規登録をAWS CLIで行います。

  • 作業をしているAWSアカウントにCLIでアクセスできるターミナル等を開き、以下の手順でアカウントをユーザープールに登録します。

  • コマンドでは、

    1. アプリケーションクライアントID
    2. 登録するEメール(受信可能なものにすること)
    3. ログインに使用するパスワード

    の3つが必要になります。

$ export APP_CLIENT_ID="xxxxxxxxxxxxxxxxxxxxxxxxxx"
$ export USER_EMAIL="email@example.com"
$ export PASSWORD="ExPassWord01@"
$ aws cognito-idp sign-up \
  --client-id ${APP_CLIENT_ID} \
  --username ${USER_EMAIL} \
  --password ${PASSWORD} \
  --user-attribute "Name=email,Value=${USER_EMAIL}" --region ap-northeast-1
  • AWS CLIコマンドがうまく通れば、以下のような出力が表示されます。
{
    "UserConfirmed": false,
    "CodeDeliveryDetails": {
        "Destination": "t***@o***",
        "DeliveryMedium": "EMAIL",
        "AttributeName": "email"
    },
    "UserSub": "0996399d-1d78-48d2-b426-*********"
}
  • 登録したメールに認証用の6桁数字が届きますので、その数字を「CONFIRMATION_CODE」として入力しCLIで認証を行います。
$export CONFIRMATION_CODE=000000
$aws cognito-idp confirm-sign-up \
  --client-id ${APP_CLIENT_ID} \
  --username ${USER_EMAIL} \
  --confirmation-code ${CONFIRMATION_CODE} --region ap-northeast-1

登録がうまくできているかユーザープールを確認します。

  • 登録したEメールと「確認ステータス」が「確認済み」になっていれば正常に登録ができています。
    17_0048.png

登録したユーザーでログインをし、IDプール(フェデレーティッド ID)から「AWS Credentials Key」を発行する方法

  • 最後に登録したユーザーでログインし、「AWS Credentials Key」を発行し、IAMが切り替わっていることを確認します。
  • まず、現在のIAMのステータスを以下のコマンドで確認します。
$aws sts get-caller-identity
  • 使用しているIAMに応じて、IAMのステータスが表示されます。
{
    "UserId": "AROAS***********:admin-sso",
    "Account": "1393******",
    "Arn": "arn:aws:sts::13931******:assumed-role/AWSReservedSSO_AdministratorAccess_22f********/admin-sso"
}
  • 以下のコマンドでIAMの切り替えに必要な情報を取得します。
  • なお、コマンド中の「IDENTITY_POOL_ID」は以下のコンソール画面で確認できます。
    18_0048.png
$export REGION="ap-northeast-1"
$export USER_POOL_ID="ap-northeast-1_xxxxx"
$export APP_CLIENT_ID="xxxxxxxxxxxxxxxxxxxxxxxxxx"
$export USER_EMAIL="email@example.com"
$export PASSWORD="ExPassWord01@"
$export IDENTITY_POOL_ID="ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$export COGNITO_USER_POOL="cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID}"

$ ID_TOKEN=$(aws cognito-idp admin-initiate-auth \
  --user-pool-id ${USER_POOL_ID} \
  --client-id ${APP_CLIENT_ID} \
  --auth-flow ADMIN_NO_SRP_AUTH \
  --auth-parameters "USERNAME=${USER_EMAIL},PASSWORD=${PASSWORD}" \
  --query "AuthenticationResult.IdToken"  --region ap-northeast-1\
  --output text) && echo ${ID_TOKEN}

$ IDENTITY_ID=$(aws cognito-identity get-id \
  --identity-pool-id ${IDENTITY_POOL_ID} \
  --logins "${COGNITO_USER_POOL}=${ID_TOKEN}" \
  --query "IdentityId"  --region ap-northeast-1\
  --output text) && echo ${IDENTITY_ID}

$ OUTPUT=$(aws cognito-identity get-credentials-for-identity \
  --identity-id ${IDENTITY_ID} \
  --logins "${COGNITO_USER_POOL}=${ID_TOKEN}"  --region ap-northeast-1) && echo ${OUTPUT}
  • 上記のコマンドが正常に通れば、以下のような出力が得られます。
  • SessionTokenは本来であればかなり長いですが、見やすくするために短く***にしています。
{
    "IdentityId": "ap-northeast-1:3a4b18c****************",
    "Credentials": {
        "AccessKeyId": "ASIA*********",
        "SecretKey": "CGByoie0****************",
        "SessionToken": "IQoJb3JpZ2l**********=",
        "Expiration": "2023-04-10T03:21:08+09:00"
    }
}
  • 得られた

    1. AccessKeyId
    2. SecretKey
    3. SessionToken

    を環境変数として代入します。

$export AWS_ACCESS_KEY_ID="ASIA*********"
$export AWS_SECRET_ACCESS_KEY="CGByoie0****************"
$export AWS_SECURITY_TOKEN="IQoJb3JpZ2l**********="
  • IAMのステータスを以下のコマンドで確認します。
$aws sts get-caller-identity
  • Cognitoから得られたIAMロールであれば以下のように、先ほど作成したIAMロールのArnが表示されます。
{
    "UserId": "AROASA37*******Y:CognitoIdentityCredentials",
    "Account": "139*******",
    "Arn": "arn:aws:sts::139******:assumed-role/Cognito_dev_id_pool_01Auth_Role/CognitoIdentityCredentials"
}

最後に

  • 元々AWS Cognitoというサービスの存在すら知らなかったのでIAMユーザーやSSO以外でAWSのkeyを渡す方法があることに驚きました。
  • 私の勉強不足かもしれませんが、今まで触ってきていたAWSのサービスとかなり毛色が違ったので、理解をするのにかなり時間がかかりました。(いまだに理解して使いこなせているのが微妙ですが、、、)
  • この記事を書くにあたり参考にした資料等を以下に記載しておりますので、AWS Cognitoの理解を深めるために是非ご一読ください。

参考資料

Amazon Cognito(ウェブ/モバイルアプリのユーザー管理)| AWS
Amazon Cognito は、開発者中心で費用対効果の高い顧客 ID およびアクセス管理 (CIAM) サービスであり、数百万人のユーザーにまで拡張可能です。
Amazon RDS(マネージドリレーショナルデータベース)| AWS
Amazon RDSは6つの人気データベースエンジンから選択できるマネージドリレーショナルデータベースサービスです。数回クリックするだけでクラウド内にリレーショナルデータベースを設定、運用、スケールすることができます。
Amazon Cognito ID プール (フェデレーティッド ID) - Amazon Cognito
Amazon Cognito ID プール (フェデレーティッド ID) は、ユーザーのために一意の ID を作成し、ID プロバイダーでそれらをフェデレートすることを可能にします。ID プールを使用すると、権限が制限された一時的な AWS 認証情報を取得して、他の AWS のサービス にアクセスすることができます。A...
Amazon Cognito user pools - Amazon Cognito
ユーザープールを使用して、ユーザー登録およびサインインをモバイルおよびウェブアプリケーションで統合します。
AWS CLIで動かして学ぶCognito IDプールを利用したAWSの一時クレデンシャルキー発行 | DevelopersIO
「Cognito IDプールってやつはAWSリソースへのアクセスを制御する認可部分を担当しているらしいけど、いったいどういう理屈でそうなってるんだ…?」 そんな自分の疑問からAWSのドキュメントを読み実際に手を動かして得られたCognito IDプールに対する理解をまとめました。

ユーザープール認証フロー - Amazon Cognito
Amazon Cognito ユーザープールとネイティブ API によるサインインプロセスの説明。サインアップ、サインイン、アカウントロックアウト、およびユーザー移行につながる API リクエストのシーケンスの説明。
プログラミングせずにCognitoで新規ユーザー登録&サインインを試してみる | DevelopersIO
Cognitoって新規ユーザー登録画面やサインイン画面をプログラミングするイメージがあって、非プログラマーには敷居が高いんだよなぁ……。そんなあなたのために、このブログを書きました。Cognitoの敷居をちょっと下げるため、プログラミング無しでCognitoを試してみます。

Qiita記事

【AWS】AWS Cognito IDプール(フェデレーティッド ID)を用いてAWSの一時「Credentials Key」を発行する方法 - Qiita
背景 AWS Cognitoはユーザーの認証と認可を処理できるサービスです。 AWS Cognitoを使用すれば、ユーザーのデータベースをAWS RDSなどのAWSの別サービスで作成することなく、ユーザーのサインアップやサイン...