Cognitoユーザープールの認証後にIDプールで権限を与える – Authorization code grant編

Cognitoユーザープールの認証後にIDプールで権限を与える - Auhorization code grant編

Cognitoユーザープールの認証後にIDプールで権限を与える(Authorization code grant編)

以下のページで、CognitoユーザープールおよびIDプールを使用し、OAuthフローはImplicit grant(暗黙の付与)の条件で、サインインユーザーにAWSリソースへアクセスするための権限を付与する構成を確認しました。

あわせて読みたい
Cognitoユーザープールの認証後にIDプールで権限を与える(Implicit Grant編) 【Cognitoユーザープールの認証後にIDプールで権限を与える】 CognitoユーザープールとIDプールを使用して、サインインユーザーにAWSリソースにアクセスするための権限...

今回はOAuthフローをAuthorization code grant(認可コードの付与)に設定した上で、同様の構成を作成します。

構築する環境

Diagram of Authorization by Cognito ID Pool after Authentication by User Pool - Aurhorization code grant ver

構成は前回と同様です。変更点は、Cognitoユーザープールのおいて、OauthフローをAuthorization code grantに設定しただけです。

Authorization code grantによる処理の流れを確認します。
Authorization code grantの場合、直接トークンを取得することはできず、代わりに認可コードを取得できます。今回は以下の流れで処理を行います。

  1. ホストされたUIページからサインインを行う。
  2. URLパラメータから認可コードを取得する。
  3. 認可コードをユーザープールのトークンエンドポイントにPOSTし、トークンを取得する。
  4. トークンを使用してIDプールにアクセスし、一時的なクリデンシャルを取得後、SSMにアクセスする。

トークンエンドポイントに関する詳細は、以下のページをご確認ください。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/token-endpoint.html

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLに、CloudFormationテンプレートに加え、ブラウザスクリプト等を配置してます。

https://github.com/awstut-an-r/awstut-fa/tree/main/035

ポイント解説

大部分が前回の構成と同様ですので、詳細はそちらをご確認ください。
本ページでは、Authorization code grantに関する内容に触れます。

CognitoユーザープールのOAuthフロー

Resources:
  UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      AllowedOAuthFlowsUserPoolClient: true
      AllowedOAuthFlows:
        - code
        #- implicit
      AllowedOAuthScopes:
        - openid
        - profile
      CallbackURLs:
        - !Sub "${BucketWesSiteEndpointUrl}/${SigninHtml}"
      ClientName: !Sub ${Prefix}-UserPoolClient
      ExplicitAuthFlows:
        - ALLOW_REFRESH_TOKEN_AUTH
        - ALLOW_USER_SRP_AUTH
      LogoutURLs:
        - !Sub "${BucketWesSiteEndpointUrl}/${SignoutHtml}"
      SupportedIdentityProviders:
        - COGNITO
      UserPoolId: !Ref UserPool
Code language: YAML (yaml)

AllowedOAuthFlowsプロパティでOAuthフローを設定します。
今回はAuthorization code grantを使用しますので、「code」を指定します。

次にホストされたUIによるサインイン/サインアウトページのURLを確認します。
それぞれ以下のURLとなります。

  • サインインページ用URL:https://[プレフィックス].auth.ap-northeast-1.amazoncognito.com/login?response_type=code&client_id=[アプリクライアントID]&redirect_uri=[サインイン後のリダイレクト先URL]
  • サインアウトページ用URL:”https://[プレフィックス].auth.ap-northeast-1.amazoncognito.com/logout?response_type=code&client_id=[アプリクライアントID]&logout_uri=[サインアウト後のリダイレクト先URL]

ポイントはURLパラメータのresponse_typeです。
Authorization code grantの場合、認可コードを取得できますので、本パラメータを「code」に設定します。

ブラウザスクリプト

JavaScriptを使用して、サインイン後のCognito機能を実装します。
AWS SDK for JavaScript v3を使用して、ブラウザスクリプトを作成する手順は、以下のページをご確認ください。

あわせて読みたい
ブラウザでAWS SDK for JavaScript v3を扱う 【ブラウザでAWS SDK for JavaScript v3を扱う】 AWSを使用してWebアプリを開発する場合、AWS SDK for JavaScriptの使用がベストプラクティスとなります。同SDKには2つ...

本ページでは、Authorization code grantでトークンを受け取るためにポイントとなる箇所を取り上げます。

認可コードとトークンエンドポイントURL

ホストされたUIによって払い出された認可コードを取得します。

const params = new URLSearchParams(window.location.search);
const code = params.get("code");

const tokenEndpoint = `https://${DOMAIN}.auth.${REGION}.amazoncognito.com/oauth2/token?grant_type=authorization_code&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&code=${code}`;
Code language: JavaScript (javascript)

認可コードはURLパラメータから取得できます。

トークンエンドポイントのURLを作成します。
認可コード等のパラメータを埋め込んでURLを作成します。

トークンエンドポイントに認可コードをPOSTして、IDトークンを取得する

const main = async () => {
  await fetch(tokenEndpoint, {
    method: "post",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    }})
    .then(response => {
      return response.json();
    })
    .then(data => {
      const idToken = data.id_token;
      ...
    })
};
Code language: JavaScript (javascript)

fetchを使用して、先ほど作成したトークンエンドポイントURLにPOSTし、IDトークンを取得します。
トークンエンドポイントの要件で、ヘッダーは「application/x-www-form-urlencoded」を指定する必要があります。

IDトークンを使用してIDプールにアクセスし、一時的なクリデンシャルを取得する

この後の流れは前回と同様です。

const ssmClient = new SSMClient({
region: REGION,
credentials: fromCognitoIdentityPool({
  client: new CognitoIdentityClient({ region: REGION }),
  identityPoolId: IDENTITY_POOL_ID,
  logins: {
    [`cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID}`]: idToken
  }
})
});

getParameter(ssmClient);
getName(idToken);
Code language: JavaScript (javascript)

IDトークンを使って、IDプールから一時的なクリデンシャルを取得します。
今回はSSMパラメータを取得することが目的ですので、SSMクライアントオブジェクトを作成後、パラメータストアにアクセスします。
加えて、IDトークンのクレームからユーザー名を取得する処理も行います。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • バケット名:fa-035
  • CognitoユーザープールのID:ap-northeast-1_27X20ZW00
  • Cognitoユーザープール アプリクライアントのID:2c45u7pnk8ubba6vf4otnubncv
  • Cognitoユーザープール ドメインプレフィックス:fa-035
  • Cognito IDプールのID:ap-northeast-1:628252c8-3ed3-473d-9141-79bdf1cbd7ee
  • SSMパラメータストアのパラメータ名:fa-035-authenticated

AWS Management Consoleからも、Cognitoの作成状況を確認します。

The Cognito user pool is successfully created.
Cognito user pool client successfully created.
OAuth authentication flow is set to "Authorization code grant".
The Cognito ID pool has been successfully created.

ユーザープールクライアントの「OAuth grant type」が「Authorization code grant」に設定されていることがわかります。
以上より、先述のホストされるUIによるサインイン/サインアウトページ用のURLは以下に定まります。

  • サインインページ用URL:https://fa-035.auth.ap-northeast-1.amazoncognito.com/login?response_type=code&client_id=2c45u7pnk8ubba6vf4otnubncv&redirect_uri=https://s3-ap-northeast-1.amazonaws.com/fa-035/signin.html
  • サインアウトページ用URL:https://fa-012.auth.ap-northeast-1.amazoncognito.com/logout?response_type=token&client_id=2c45u7pnk8ubba6vf4otnubncv&logout_uri=https://s3-ap-northeast-1.amazonaws.com/fa-035/signout.html

S3バケットにHTMLを設置する

S3バケットにHTMLを設置し、サインイン/サインアウト後のコンテンツを用意します。
先述のサインイン/サインアウト用URLをindex.htmlに記載後、AWS CLIを使用して設置します。

$ aws s3 cp ./html s3://fa-035/ --recursive

$ aws s3 cp main.js s3://fa-035
Code language: Bash (bash)

認証ユーザー向けコンテンツにアクセスする

準備が整いましたので、実際にホストされたUIにアクセスします。
以下のURLにアクセスします。

https://s3-ap-northeast-1.amazonaws.com/fa-035/index.html

するとルートページであるindex.htmlが表示されます。

Access the Cognito user pool sign-in page.

「Sign In」を押下すると、サインインページが表示されます。

初回に限り、サインアップ処理を必要です。サインアップ処理に関しては、以下のページをご確認ください。

あわせて読みたい
Cognito ユーザープールでサインインページを作成する 【CognitoユーザープールのホストされたUIでサインインページを作成する】 Cognitoを使用してサインインページを作成します。 CognitoはAWSが提供する認証系サービスで...

今回は「awstut」というユーザー名を登録します。
メールアドレスおよびパスワードを入力後、「Sign In」を押下します。

If you have successfully signed in, you can access AWS resources.

Implicit grantの時と同様に、ユーザー名とSSMパラメータストアの値が表示されました。

まとめ

OAuthフローがAuthorization code grantの場合でも、Cognitoトークンエンドポイントに認可コードをPOSTすることによって、トークンが取得できます。
そしてトークンを使ってIDプールにアクセスすることによって、一時的なクリデンシャルを取得することが可能で、これによってAWSリソースにアクセスが許可されます。