[AWS CloudFormation][AWS SAM] Cognito ユーザプール、アプリクライアント定義

# ユーザプール定義

構文については[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpool.html)参照

設定したい項目以外はデフォルトで定義したものが以下

```yaml
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: !Sub '${StackName}_UserPool'
      UsernameConfiguration: 
        CaseSensitive: false
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: true
      AccountRecoverySetting:
        RecoveryMechanisms:
          - Name: admin_only
            Priority: 1
      LambdaConfig:
        PreAuthentication: !GetAtt PreAuthenticationHook.Arn
```



## マネージメントコンソールで内容確認



### 属性

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/71d614e1-1245-0348-4c42-3d64e0dd630c.png)

- サインインに使用する属性は`ユーザ名`

  Emailや、電話番号を使用する場合は、`AutoVerifiedAttributes`で指定する

- 追加属性はなし

  追加したい場合は、`AliasAttributes`で指定する

- ユーザ名入力で大文字、小文字を区別しない
  
テンプレートの以下部分で設定
  
  ```yaml
        UsernameConfiguration:
          CaseSensitive: false
  ```
  
  

### ポリシー

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/1876a582-59b9-2fda-3b60-b1cdb73a77d9.png)

- 管理者のみサインアップ可能とする

  テンプレートの以下部分で設定

```yaml
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: true
```



### MFAそして確認

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/d015a5fa-f1ef-4a73-b734-e08cd38488a0.png)

- アカウント回復方法をなしとする

  テンプレートの以下部分で設定

  ```yaml
        AccountRecoverySetting:
          RecoveryMechanisms:
            - Name: admin_only
              Priority: 1
  ```



### トリガ

![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/26e351ca-ef89-369f-4159-426470297b64.png)

- 認証前にフックするLambdaを指定

  テンプレートの以下部分で設定

  ```yaml
        LambdaConfig:
          PreAuthentication: !GetAtt PreAuthenticationHook.Arn
  ```

  上記以外のタイミングでフックするLambda設定に関しては[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-userpool-lambdaconfig.html)参照

  以下、Lambdaの定義例
  関数本体と、Cognitoに与えるLambda実行権限を定義

  ```yaml
    PreAuthenticationHook:
      Type: AWS::Serverless::Function
      Properties:
        FunctionName: !Sub '${StackName}_PreAuthenticationHook'
        CodeUri: pre-Authentication-hook/
        Handler: function.lambda_handler
        Runtime: python3.8
  
    LambdaAddPermission:
        Type: AWS::Lambda::Permission
        Properties:
          Action: lambda:InvokeFunction
          FunctionName: !GetAtt PreAuthenticationHook.Arn 
          Principal: cognito-idp.amazonaws.com
  ```

# アプリクライアント定義

構文については[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolclient.html)参照

設定したい項目以外はデフォルトで定義したものが以下

```yaml
  UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      UserPoolId: !Ref UserPool # 定義したユーザプールを参照
      ClientName: !Sub '${StackName}_clientApp'
      GenerateSecret: false
      PreventUserExistenceErrors: ENABLED
```



## マネージメントコンソールで内容確認



### アプリクライアント

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/93dd05b4-8283-9173-2663-180cf8d8d2bc.png)

- アプリクライアントのシークレットなし

  テンプレートの以下部分で設定

  ```yaml
  GenerateSecret: false
  ```

- ユーザの存在エラーを防ぐを有効設定

  テンプレートの以下部分で設定

  ```yaml
  PreventUserExistenceErrors: ENABLED
  ```

  

### トークンの有効期限設定

```yaml
  UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      UserPoolId: !Ref UserPool
      ClientName: !Sub '${StackName}_clientApp'
      GenerateSecret: false
      RefreshTokenValidity: 2
      AccessTokenValidity: 1
      IdTokenValidity: 1
      PreventUserExistenceErrors: ENABLED
```

上記のように

- 更新トークンの有効期限：2
- アクセストークンの有効期限：1
- IDトークンの有効期限：1

と設定してみたところ、以下のように日に値が設定された

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/131af3ca-7a8f-fc5f-1fe1-a219932ba1f4.png)

分単位の設定ができない。。

以下、各設定値の最大値から単位は秒と考えられるが、マネジメントコンソールで秒は設定できないのでそれもおかしい

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/4927c426-1584-3352-296d-9eacd6fda165.png)

とりあえずAWSに不具合があるようなので、有効期限は全てデフォルトで運用