🐕

AWS CognitoでサインアップしたユーザをLambdaでDynamoDBに登録する

2022/03/13に公開

概要

AWS Cognito でサインアップ(登録)したユーザを、DB(DynamoDB)に登録したいというケースは割と存在するかと思います。
※前提として、Cognito はユーザマスタとしては使用すべきではなく、DB は別に持つことが推奨されています。

そこで、今回は、AWS Cognito でサインアップしたユーザを Lambda で DynamoDB に登録する為の最小構成を作ってみます。

実現方法としては、画面側で CognitoSDK を呼び出した後に DynamoDB に Insert しに行くなどの方法も考えられるかと思いますが、画面側処理に依存するのは望ましくないため、バックエンド側で、Cognito のトリガー機能を用いて、E-mail などの認証が完了したタイミングで、Lambda を呼び出し、ユーザ情報を DB(DynamoDB)に連携します。

構成

今回実施するのは以下のような最小構成とします。
実際には、Cognito の E-mail 認証前の登録画面や、認証後の追加会員情報登録画面などを作り、必要な会員情報を登録させるようにすると良いでしょう。

  • Cognito で保持するデータ
    • ユーザ名(id):cognito が払い出した UUID
    • ログイン ID(E-mail):ユーザ登録時に入力した e-mail(有効性確認済)
    • パスワード:ユーザ登録時に入力したパスワード
  • DynamoDB で保持するデータ
    • id : cognito が払い出した UUID。パーティションキー
    • E-mail:ユーザ属性情報としての E-mail アドレス

前提

  • Cognito ユーザプールは構成済みであること
  • DynamoDB にユーザテーブルを作成済みであること
  • Lambda ランタイム:今回は Node.js を使用します

なお、Cognito ユーザプールを SAM で作成している場合は、呼び出す Lambda トリガ、Lambda もまとめて SAM で設定できると思いますが、今回は、個別に Cognito が作成済み(個別に紐づけ設定が必要)の前提とします。

また、この Lambda トリガーは会員登録時以外に、パスワード忘れからの確認にもコールされると思いますので、既に会員登録済の場合の考慮は別途行う必要があります。

構築方法

lambda 関数の準備

次のような内容の Lambda 関数を作成します。

行っている処理の内容としてはシンプルで、eventで cognito 側からユーザの E-mail 確認が完了したタイミングで、対象ユーザの情報を受け取り、DynamoDB のUserという名前のテーブルに対して、Cognito のユーザ名(UUID)をキーにして、属性情報と共にputItem行っています。

signup-link-lambda.js
const dynamodb = require("aws-sdk/clients/dynamodb");
const docClient = new dynamodb.DocumentClient();

exports.signupLinkToDBHandler = async (event, context, callback) => {
  var params = {
    TableName: "User",
    Item: {
      id: event.userName,
      email: event.request.userAttributes.email,
    },
  };
  const result = await docClient.put(params).promise();
  console.log(
    `cognito user link to dynamodb id=${event.userName} email=${event.request.userAttributes.email} result=${result}`
  );

  callback(null, event);
};

DynamoDB へのアクセス権の付与

この処理を実行するためには、lambda 関数が DynamoDB にアクセスできる必要があります。対象の Lambda の実行ロール(IAM ロール)に対して、DynamoDB の対象テーブルに対して Put する権限を付与します。

DynamoDB の各種操作権限一式を与える場合はAmazonDynamoDBFullAccessになります。(必要に応じて細かい権限を設定してください)

SAM テンプレートの定義例を記載しておきます。(SAM で構築する場合、AWS コンソールから登録する場合は、権限を個別に設定してください)

ポイントとしては、Policiesに対してAmazonDynamoDBFullAccessを設定しているところくらいになります。

template.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: >-
  cognito-trigger-sample
Transform:
  - AWS::Serverless-2016-10-31
Resources:
  signupLinkToDBFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/signup-link-lambda.signupLinkToDBHandler
      Runtime: nodejs14.x
      Architectures:
        - x86_64
      MemorySize: 128
      Timeout: 100
      Description: Link cognito users to DB.
      Policies:
        - AWSLambdaBasicExecutionRole
        - AmazonDynamoDBFullAccess

Cognito のトリガ設定

Cognito 側から、E-mail 確認時に Lambda 関数を呼び出すように以下のように設定します。

  1. AWS コンソールから、Cognito-ユーザプールで対象のユーザプールを選択します。
  2. 全般設定-トリガーを選択します。
  3. 確認後の項目で対象の Lambda 関数を選択し、変更の保存を押下して設定を反映します。

以上の設定で、Cognito でユーザ登録して E-mail 確認を行うと、DynamoDB に対して、ユーザ情報が Put されるようになります。

※正常に動作しない場合は、CloudWatchLogs にログが出力されていると思いますので、確認してみてください。

Discussion