Serverlesss(AWS Lambda)(2)cognito設定

cognito を利用した認証機能の作成

今回の手順

  • serverless framework を利用した cognito のセットアップ
  • ユーザの作成・認証テスト
  • トリガーの使い方

serverless.yml を利用した cognito のセットアップ

cognito のセットアップに利用するプロジェクトを作成します。

今回は最小限の構成で cognito をセットアップします

# 以下を追記
resources:
  Resources:
    CognitoUserPool:
      Type: AWS::Cognito::UserPool
      Properties:
        UserPoolName: ${self:app}-user-pool # 任意の名前を指定

    CognitoUserPoolClient:
      Type: AWS::Cognito::UserPoolClient
      Properties:
        UserPoolId:
          Ref: CognitoUserPool
        ExplicitAuthFlows:
          - ALLOW_USER_PASSWORD_AUTH # パスワード認証に必要
          - ALLOW_USER_SRP_AUTH # SDKによる認証に必要
          - ALLOW_REFRESH_TOKEN_AUTH # RefreshTokenによる認証に必要

デプロイ

serverless deploy

AWS consoleよりユーザープールが作成されていることを確認します

ユーザープールを選択し、プール ID とアプリクライアント ID を控えておきます。

ユーザの作成・認証テスト

コンソール上でユーザの作成・認証ができることを確認していきます

ユーザ登録の確認

Username が Email となっていることに注意してください
Cognito では認証に使用するユニークな値を Username として利用するようになっています

curl https://cognito-idp.us-east-1.amazonaws.com \
-XPOST \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.SignUp' \
-H 'Content-Type: application/x-amz-json-1.1' \
-d '{"ClientId": [アプリクライアントID], "Username": "test@example.com", "Password": "Test1234!" }'
{
  "ClientId": [アプリクライアントID],
  "Username": "test@example.com",
  "Password": "Test1234!"
}

1)レスポンスがエラーでなければユーザが追加されているはずなのでaws console上で確認を行います

2)アカウントのステータスが UNCONFIRMED となっているのでユーザを選択してユーザの有効化を行います。

3)ユーザーの有効化を行うとステータスが CONFIRMED に変更されます

パスワードによる認証確認

このパスワードによる認証確認のために ALLOW_USER_PASSWORD_AUTH のオプションが必要になります。

curl https://cognito-idp.us-east-1.amazonaws.com \
-XPOST \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
-H 'Content-Type: application/x-amz-json-1.1' \
-d '{"ClientId": [アプリクライアントID], "AuthFlow": "USER_PASSWORD_AUTH", "AuthParameters": { "USERNAME": "test@example.com", "PASSWORD": "Test1234!" }}'
{
  "ClientId": [アプリクライアントID],
  "AuthFlow": "USER_PASSWORD_AUTH",
  "AuthParameters": {
    "USERNAME": "test@example.com",
    "PASSWORD": "Test1234!"
  }
}

リクエストが成功すると以下のようなレスポンスがあるのでRefreshTokenを控えます
次のリフレッシュトークンでの認証に使用します

{
  "AuthenticationResult": {
    "AccessToken": "...",
    "ExpiresIn": 3600,
    "IdToken": "...",
    "RefreshToken": "...", // <== これを控える
    "TokenType": "Bearer"
  },
  "ChallengeParameters": {}
}

リフレッシュトークンでの認証

先ほど控えた RefreshToken を利用してセッションを確認します

curl https://cognito-idp.us-east-1.amazonaws.com \
-XPOST \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
-H 'Content-Type: application/x-amz-json-1.1' \
-d '{"ClientId": "6q13el38vb7pppet579747bidf", "AuthFlow": "REFRESH_TOKEN_AUTH","AuthParameters": { "REFRESH_TOKEN": [リフレッシュトークン]"}}'

パスワードによる認証確認と同じレスポンスがあれば OK です

{
  "ClientId": [アプリクライアントID],
  "AuthFlow": "REFRESH_TOKEN_AUTH",
  "AuthParameters": {
    "REFRESH_TOKEN": [リフレッシュトークン]
  }
}

SDK による React への導入をしてみたのでこちらのリポジトリも確認してみてください
React への導入サンプル 『https://github.com/naok1207/react-cognito-auth』

react-cognito-auth

トリガーについて

cognito ではトリガーという概念があり、AWS Lambda 関数を使用して認証のカスタマイズをすることができます。

今回は試しにユーザー登録時にユーザの有効化を自動で行えるようにしてみます。(現状では先ほど行ったように一度 AWS Console 上で有効化をする必要があります)

1)トリガー用の関数を作ります

handler.jsに追記

module.exports.preSignUp = async (event, _context, callback) => {
  event.response.autoConfirmUser = true;

  callback(null, event);
}

2)関数のデプロイを行います

serverless.ymlに追記

functions:
  ...
  # 追記
  preSignUp:
    handler: handler.preSignUp
    events:
      - cognitoUserPool:
          pool: ${self:app}-user-pool # 任意に指定したUserPoolName
          trigger: PreSignUp # トリガーの名前
          existing: true # 作成済みのユーザープールを利用する

デプロイ

serverless deploy

この状態で先ほど行った『ユーザ登録の確認』を再度実行すると最初からCONFIRMED となっていることが確認できるはずです。

このようにトリガー関数を利用して認証をカスタマイズすることができます。

以上で cognito を利用した認証機能の作成 は終了とします。

追記

UserPoolUserPoolClientのオプションを調べたので追記しておきます

UserPool のオプションについて

## プロパティ全体
Type: AWS::Cognito::UserPool
Properties:
  # ユーザがパスワードを忘れた際のリカバリ設定
  AccountRecoverySetting: AccountRecoverySetting
  # 管理者にのみユーザーの作成を許可するか、ユーザーに自己サインアップを許可するかの設定(デフォルトでは自己サインアップが許可される) in policy
  AdminCreateUserConfig: AdminCreateUserConfig
  # ユーザープールのエイリアスの設定
  AliasAttributes:
    - String # phone_number, email, preferred_username
  # 自動で検証される属性の設定
  AutoVerifiedAttributes:
    - String # email, phone_number
  # デバイスを記録するための設定 よりセキュアなシステムを構築する際に使用
  DeviceConfiguration: DeviceConfiguration
  # 認証関連に利用するEmailの設定
  EmailConfiguration: EmailConfiguration # (デフォルト COGNITO_DEFAULT 使用上限あり)
  # MFA認証の有効設定
  EnabledMfas:
    - String
  # トリガーの設定 functions内部でも行える
  LambdaConfig: LambdaConfig
  # MFA認証の対象者の設定
  MfaConfiguration: String
  # ポリシーの設定 (主にパスワードポリシーの設定)
  Policies: Policies
  # ユーザープールのスキーマ設定
  Schema:
    - SchemaAttribute
  # SMS認証で表示するメッセージ
  SmsAuthenticationMessage: String
  # SMSの設定
  SmsConfiguration: SmsConfiguration
  # emailや電話番号の変更に関する設定
  UserAttributeUpdateSettings: UserAttributeUpdateSettings
  # ユーザー名に使用する属性の設定
  UsernameAttributes:
    - String # phone_number or email
  # 大文字と小文字の区別を行うかどうかの設定
  UsernameConfiguration: UsernameConfiguration
  # 高度なセキュリティモードの有効化設定 IPアドレスの制限などができるみたい?
  UserPoolAddOns: UserPoolAddOns
  # ユーザープールの名前の設定
  UserPoolName: String
  # ユーザープールを分類するために利用するタグの設定
  UserPoolTags: Json
  # 様々な確認メッセージのテンプレートの設定
  VerificationMessageTemplate: VerificationMessageTemplate

詳しくは

AWS::Cognito::UserPool

参考

https://www.serverless.com/

https://www.serverless.com/framework/docs/providers/aws/guide/events