🔑

【AWS】Amplifyを使わずに最小構成でCognitoログイン及びクライアント認証を実装する

2021/08/28に公開

Amplifyを使わずにCognitoログイン及びクライアント認証を実装する方法です。
この記事ではJavaScriptを例に紹介しますが、SDKを使わずにAPIを直接叩くため、言語によらず実装可能です。

Cognitoの設定

ユーザープールの管理

ユーザープールとは

ユーザープールとは、ユーザーのサインアップやサインインを提供するユーザディレクトリです。
Cognitoでユーザー管理をするために必要なもの、という認識で大丈夫です。
より詳しく知りたい方は、以下公式ドキュメントをご覧ください。
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-identity-pools.html

ユーザープールの作成

まずはユーザープールを作成します。
AWSマネージメントコンソールにサインインし、サービスからCognitoを検索して開き、「ユーザープールの管理」をクリックします。

次に、右上に表示されている「ユーザープールを作成する」をクリックします。

任意のプール名を入力し、「デフォルトを確認する」をクリックします。
ここで入力するプール名はアカウントを管理したいサービス名など、わかりやすい名前をつけておくと良いと思います。

パスワード強度の変更

サイドメニューの「ポリシー」からパスワードの強度を変更します。
今回はテスト用なので、全てのチェックを外して「変更の保存」をクリックします。

アプリクライアントの追加

次に、サイドメニューの「アプリクライアント」から、「アプリクライアントの追加」をクリックします。

任意のアプリクライアント名を入力し、「クライアントシークレットを生成」のチェックを外します。
その後、「アプリクライアントの作成」をクリックします。

プールの作成

最後に、サイドメニューの「確認」をクリックし、入力内容を確認して「プールの作成」をクリックします。

アプリクライアントの設定

プールの作成が完了したら、後ほど利用するアプリクライアントIDをメモに控えておきます。
サイドメニューの「アプリクライアントの設定」をクリックし、IDをコピーしてメモに控えておきます。

有効なIDプロバイダの「Cognito User Pool」にチェックを入れ、Cognitoの認証を利用するようにします。

「サインインとサインアウトのURL」の「コールバックURL」にログイン後にリダイレクトしたいURLを指定します。
今回はローカルサーバでテストするため、http://localhost:8080/を指定します。

次に、cognitoのログイン画面でログイン後に返される情報を設定します。
「OAuth2.0」の「許可されているOAuthフロー」の「Authorization code grant」にチェックを入れます。
ここにチェックを入れると、ログイン後に認可コードを取得可能になります。

続いて、「許可されているOAuthスコープ」では「openid」にチェックを入れて、「変更の保存」をクリックします。

ドメイン名

続いて、Cognitoのドメイン名を設定します。
今回利用するAPIエンドポイントや、ログイン画面のドメインになります。

任意のドメイン名を入力し、「使用可能かチェク」をクリックして使用可能なことを確認して、「変更の保存」をクリックします。

これでユーザープールの作成が完了しました。

ユーザーを作成

次に、ログインに必要なユーザを作成します。

サイドメニューの「ユーザとグループ」をクリックし、「ユーザの作成」をクリックします。

ユーザ名と仮パスワード、Eメールを入力し、その他チェックは外します。

入力が完了したら、「ユーザーの作成」をクリックします。

これでログインに必要なユーザが作成できました。

ログインして認可コードを取得

次に、Cognitoが用意しているログイン画面を利用して先程作成したユーザでログインし、リダイレクトされることを確認します。
また、リダイレクトされた際に、URLに認可コードが付与されていることも確認します。

ログイン

「アプリクライアントの設定」から、「ホストされたUIを起動」をクリックします。

先程作成したユーザ名と仮パスワードを入力して、「Sign in」をクリックします。

すると、パスワードの設定をするように促されるので、入力し「Send」をクリックします。

リダイレクトURLに認可コードが付与されていることを確認

予め作成したローカル環境のページに遷移され、リダイレクトURLにcode=xxxという認可コードが付与されていることが確認できます。

この認可コードを使って、クライアントからユーザ認証を行います。

クライアント認証

ログインができたので、次に認可コードを使ってユーザのクレデンシャルを取得します。
クライアントでユーザ認証されているかどうかを判定する場合は、この認証を利用します。
また、ユーザ情報を取得する場合は、ここで取得するクレデンシャルを用いて取得します。

認可コードを用いてクレデンシャルを取得

Cognitoのログイン画面からログイン後、リダイレクトURLに付与された認可コードを用いて、以下エンドポイントにアクセスしてクレデンシャルを取得します。
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/token-endpoint.html

curlでリクエストする

まずは、認可コードを用いてクレデンシャルを取得できることを確認するため、curlコマンドを用いて確認します。

$ curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id={クライアントID}" \
  -d "scope=openid" \
  -d "redirect_uri=http://localhost:8080/" \
  -d "code={認可コード}" \
  "https://test0987.auth.ap-northeast-1.amazoncognito.com/oauth2/token"
  
{
  "id_token":"xxxxxx", # ユーザ情報がJWT形式で格納されているトークン
  "access_token":"xxxxx", # ユーザ情報などを取得する際に利用するトークン
  "refresh_token":"xxxxx", # 再認証するためのトークン
  "expires_in":3600, # トークンの有効期限(単位:秒)
  "token_type":"Bearer" # トークンタイプ
}

クレデンシャルが取得できました。
IDトークンはJWT形式でユーザ情報が入っています。
https://jwt.io/ にIDトークンを貼り付けてデコードすると、次のようにユーザ情報が確認できます。

JavaScriptでリクエストする

curlでリクエストが成功したので、続いてJavaScriptで認可コードを用いてクレデンシャルを取得するコードを実装します。

Cognitoログイン画面からリダイレクト後、以下コードを実行します。
※クライアントIDなどは適宜置き換えてください。

async function postData(url, data) {
  const response = await fetch(url, {
    method: 'POST',
    cache: 'no-cache',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: data,
  });
  return response.json();
}

// URLから認可コード取得
const query = location.search.replace('?', '');
const authCode = query.split('=')[1];

const clientId = 'クライアントID';
const endpoint = 'https://test0987.auth.ap-northeast-1.amazoncognito.com/oauth2/token';

// application/x-www-form-urlencoded形式でbodyを作成
const requestBody = `grant_type=authorization_code&client_id=${clientId}&scope=openid&redirect_uri=http://localhost:8080/&code=${authCode}`;

postData(endpoint, requestBody).then((data) => {
  console.log(data);
});

無事にクレデンシャルが取得できました。

以上が、Amplifyを使わずに最小構成でCognitoログイン及びクライアント認証を実装する方法でした。

Discussion