【AWS】Congnitoを用いたログイン機能


## Cognitoとは

公式の定義では以下の通りである。要約するとログイン機能を実装できる機能である。


>Amazon Cognito を使用すると、ユーザーのサインアップおよびサインイン機能を追加し、ウェブおよびモバイルアプリケーションへのアクセスを制御できます。

https://aws.amazon.com/jp/cognito/

## ログイン画面の作り方

オリジナル(旧)コンソール画面と新しい(他のAWSサービス画面に似ている)コンソール画面の二つやり方があるが、今回は新しいコンソール画面での作り方を紹介する。

1. [Amazon Cognito コンソール](https://console.aws.amazon.com/cognito/home)に移動する
1. 画面左の[ユーザー プール]を選択する
1. 右上の[ユーザー プールの作成]を選択する
1. サインインエクスペリエンスの設定画面で、Cognito ユーザープールのサインインオプションでEメールと電話番号を選択する
    ここでフェデレーテッドアイデンティティプロバイダーはSNS認証のことである
    >ユーザーは、Facebook、Google、Amazon、Apple などのソーシャルアイデンティティプロバイダーの認証情報を使用して、サインインできます。
    
    ![Cognito5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/d06fae7a-aba0-0cce-9396-bfe11180e397.png)
1. セキュリティ要件の設定画面で、パスワードポリシー、多要素認証の有無、ユーザーアカウントの復旧の仕方を設定する
    ![Cognito6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/689f8530-9e7f-11b1-ade7-19ad28cd0051.png)
    ![Cognito7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/7f181cad-7491-4511-3aba-606c86d77901.png)
    ![COgnito_4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/130b193a-881d-9b37-2d96-be6b83b6aa8a.png)
1. サインアップエクスペリエンスの設定で、セルフサインアップの踏む、属性検証とユーザーアカウントの確認、必須の属性を設定する
    ![Cognito_5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/2e02824f-edb9-4469-6609-4954780e77c1.png)
    ![Cognito_6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/1b4d6b0f-e0cc-c616-c1c0-e6de29fe59f1.png)
    ![Cognito_7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/fbc9ca4c-52e1-4263-4b12-c0cba3763efb.png)
1. メッセージ配信の設定で、E メール、SMSの送信方法を設定する
    ![Cognito_8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/26673c02-699f-912d-7681-9663e89d6ee7.png)
    ![Cognito_9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/7d56aca3-4163-3240-8795-4abec6d6db80.png)
1. アプリケーションの統合で、ユーザープール名、ホストされた認証ページの使用の有無、ドメイン、最初のアプリケーションクライアント、高度なアプリケーションクライアントの設定を設定する
    ![Cognito8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/e374da05-70f6-0303-24a7-df39dbd94a99.png)
    ![Cognito_11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/4f5c6432-a540-d914-fce2-dcaae8cc37f8.png)
1. 確認および作成で設定を確認し、ユーザープールを作成を押す
:::note warn
※SMSメッセージのセットアップを要求された場合、以下のサイトに従って、電話番号の取得(有料)とSMS 使用量クォータの引き上げを行う
https://us-east-1.console.aws.amazon.com/pinpoint/home
https://docs.aws.amazon.com/sns/latest/dg/channels-sms-awssupport-spend-threshold.html
:::

## ログイン画面の開き方

1. [Amazon Cognito コンソール](https://console.aws.amazon.com/cognito/home)に移動する
1. ユーザープール名を選択する
1. アプリケーションの統合のタブからアプリケーションクライアントのリストのアプリケーションクライアント名を開く
1. ホストされた UI を表示を押す

![Cognito_12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/d8512a82-eb82-37bb-076b-30a1d882c9a1.png)

![Cognito_15.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/1f75223c-9afb-bdac-2606-0fe687c1c115.png)

ホストされた UIの規則
```
https://<your user pool domain>/authorize?client_id=<your app client ID>&response_type=<code/token>&scope=<scopes to request>&redirect_uri=<your callback URL>
```

ログイン Cognito からコールバックページにリダイレクトされたURLは、末尾にcode というクエリ文字列が付与される。
```
http://localhost:8080/callback.php&code=XXXXX
```
code=********は、Authentication code と呼ばれる

## ID プールの作成
1. Cognitoコンソール画面の左側「IDプール」を押す
1. ID プールの信頼を設定を入力する
    ![IDpool1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/01319a89-c1a5-d835-109d-0d4858d43f74.png)
1. IAM ロールを設定する
    ![IDpool2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/078ee146-436a-9b04-c95e-e1f0f4861079.png)
1. ID プロバイダーを接続の設定をする
    ![IDpool3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/0fed3a28-84dd-4c82-72c7-f1c4aad60e42.png)
    ![IDpool4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/e82123e5-40b1-8345-f947-e4ad6f0e2e97.png)
1. プロパティを設定をする
    ![IDpool5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/ed9c3831-a0c0-766f-8041-3a236d4cc220.png)
1. ID プールを作成を押す


## Node.jsからCUIでサインインしてみる
下記のTypescriptコードsample.tsを作って、コンパイルし、nodeでコンソール上で実行してみる

```terminal
mkdir MycognitoJS
cd MycognitoJS
npm install -g typescript
npm install aws-amplify
tsc –-init
tsc .\sample.ts
node .\sample.js
```

```typescript:sample.ts
import { Amplify, Auth } from 'aws-amplify';

// 使用するユーザープール、クライアントの ID を指定
Amplify.configure({
  Auth: {
        region: 'us-east-1',
    userPoolId: 'us-east-1_*******',
    userPoolWebClientId: '7********************',
  }
});

async function signIn() {
  const username = 'User-1';
  const password = 'Password-1';
  try {
    const user = await Auth.signIn(username, password);
    console.log(user);
    // console.log(user.attributes.email);
  } catch (error) {
    console.error(error);
  }
}

signIn();
```

成功すると、以下のような出力が標準出力に表れる。


```termianl
CognitoUser {
  username: '*****',
  pool: CognitoUserPool {
    userPoolId: 'us-east-1_**********',
    clientId: '******************************',
    client: Client {
      endpoint: 'https://cognito-idp.us-east-1.amazonaws.com/',
      fetchOptions: {}
    },
    advancedSecurityDataCollectionFlag: true,
    storage: [Function: MemoryStorage] {
      setItem: [Function (anonymous)],
      getItem: [Function (anonymous)],
      removeItem: [Function (anonymous)],
      clear: [Function (anonymous)]
    },
    wrapRefreshSessionCallback: [Function (anonymous)]
  },
  Session: null,
  client: Client {
    endpoint: 'https://cognito-idp.us-east-1.amazonaws.com/',
    fetchOptions: {}
  },
  signInUserSession: CognitoUserSession {
    idToken: CognitoIdToken {
      jwtToken: '****************************************************************',
      payload: [Object]
    },
    refreshToken: CognitoRefreshToken {
      token: '********************************************************'
    },
    accessToken: CognitoAccessToken {
      jwtToken: '**********************************',
      payload: [Object]
    },
    clockDrift: 0
  },
  authenticationFlowType: 'USER_SRP_AUTH',
  storage: [Function: MemoryStorage] {
    setItem: [Function (anonymous)],
    getItem: [Function (anonymous)],
    removeItem: [Function (anonymous)],
    clear: [Function (anonymous)]
  },
  keyPrefix: 'CognitoIdentityServiceProvider.****************',
  userDataKey: 'CognitoIdentityServiceProvider.******************************',
  attributes: {
    sub: '47*************************',
    email_verified: true,
    email: '*****@email.com'
  },
  preferredMFA: 'NOMFA'
}
```



## まとめ
今回は、AWS Congnitoを使ったログインページ作成方法を紹介した。

## 参考サイト

https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html