LoginSignup
1
1

More than 3 years have passed since last update.

Cognito+API Gateway+Lambdaでユーザ作成APIを作りたいんだー!

Last updated at Posted at 2020-05-01

AWSの認定は保有していますが
実践できていない主なサービスがサーバレスまわり…

ということで勉強を兼ねて、簡単なAPIを作成してみます。

やりたいこと

APIでユーザ作成
- ログイン名 と パスワードをリクエストボディに指定しAPIをコールするだけでユーザ作成する。
- メールアドレス/電話番号の認証は不要。

参考

LambdaでCognito認証(ユーザー作成)

やってみよう!

ユーザプールの作成

こんな私でもCognitoでユーザ管理をするにはユーザプールを作成しなければならないことは知っている。

属性は必要最低限を指定
image.png

image.png

image.png

image.png

認証フローはよくわからないため全てチェック。※今後勉強します
ALLOW_USER_PASSWORD_AUTH が絶対必要
「クライアントシークレットを作成」にはチェックを入れないこと。
image.png

Lambda用IAMロール

Lambdaの基本的なポリシーに加えて、「AmazonCognitoPowerUser」をアタッチする。
image.png

ユーザ作成用のLambdaを作成

今回、ソースコード内のアプリクライアントID,ユーザプールIDはLambdaの環境変数にセットしています。
作成するユーザはすぐに使える状態にしたかったので、adminConfirmSignUpを利用して確認済み(CONFIRMED)のステータスに変更しています。
バリデーションやエラー処理は適当なので、適宜変更をお願いします。

index.js
'use strict';

const AWS = require('aws-sdk');
const cognito = new AWS.CognitoIdentityServiceProvider();

/**
 * SignUp
 */
exports.handler = async (event, context) => {
  const response = {};
  let loginName;
  let password;
  console.log(event);

  // Validation
  if (!(event.body) || !('loginName' in JSON.parse(event.body)) || !('password' in JSON.parse(event.body))) {
    response["statusCode"] = 400;
    return response;

  } else {
    let reqestBody = JSON.parse(event.body);

    loginName = reqestBody["loginName"];
    password = reqestBody["password"];
  }

  // SignUp parameters
  const params = {
    ClientId: process.env['APP_CLIENT_ID'],
    Username: loginName, 
    Password: password
  };

  response["headers"] = {"Access-Control-Allow-Origin" : "*", "Content-Type" : "application/json"};

  // SignUp
  try {
      const user = await cognito.signUp(params).promise();
      console.log('User sign up success!!!', JSON.stringify(user, null, 4));


      const confirmParams = {};
      confirmParams['UserPoolId'] = process.env['USER_POOL_ID'];
      confirmParams['Username'] = loginName;
      const result = await cognito.adminConfirmSignUp(confirmParams).promise();

      console.log('result : ' + JSON.stringify(result));

      response["statusCode"] = 201;
      response["body"] = JSON.stringify({"loginName" : loginName});
      return response;
  }
  catch(err) {
      console.log('User sign up failed...' + err);

      if (err.code == 'UsernameExistsException') {
          response["statusCode"] = 409;
      } else if (err.code == 'InvalidPasswordException') {
          response["statusCode"] = 400;
      } else {
          response["statusCode"] = 500;
      }

      return response;
  }
};

Lambdaのテスト

image.png

テストを実行
image.png

ユーザプールにユーザが作成された。
ステータスもCONFIRMEDになっている。めでたい!
image.png

API Gatewayの作成

image.png

「Lambdaプロキシの統合」にチェックを入れ、作成したLambda関数を選択する。
image.png

API Gatewayからのテスト実行
image.png

こちらもユーザが作成された。めでたい!!!
image.png

その後、メールアドレスや電話番号が指定された場合はその値をCognitoに登録するソースへ編集しました。

index.js
'use strict';

const AWS = require('aws-sdk');
const cognito = new AWS.CognitoIdentityServiceProvider();

/**
 * SignUp
 */
exports.handler = async (event, context) => {
  const response = {};
  let loginName;
  let password;
  let userAttributes;
  console.log(event);

  // Validation
  if (!(event.body) || !('loginName' in JSON.parse(event.body)) || !('password' in JSON.parse(event.body))) {
    response["statusCode"] = 400;
    return response;

  } else {
    let reqestBody = JSON.parse(event.body);

    loginName = reqestBody["loginName"];
    password = reqestBody["password"];
    userAttributes =[];

    if('email' in JSON.parse(event.body)) {
      userAttributes.push({'Name':'email','Value':reqestBody["email"]});
    }
    if('phone' in JSON.parse(event.body)) {
      userAttributes.push({'Name':'phone_number','Value':reqestBody["phone"]});
    }
  }

  // SignUp parameters
  const params = {
    ClientId: process.env['APP_CLIENT_ID'],
    Username: loginName, 
    Password: password,
    UserAttributes:userAttributes
  };

  response["headers"] = {"Access-Control-Allow-Origin" : "*", "Content-Type" : "application/json"};

  // SignUp
  try {
      const user = await cognito.signUp(params).promise();
      console.log('User sign up success!!!', JSON.stringify(user, null, 4));


      const confirmParams = {};
      confirmParams['UserPoolId'] = process.env['USER_POOL_ID'];
      confirmParams['Username'] = loginName;
      const result = await cognito.adminConfirmSignUp(confirmParams).promise();

      console.log('result : ' + JSON.stringify(result));

      response["statusCode"] = 201;
      response["body"] = JSON.stringify({"loginName" : loginName});
      return response;
  }
  catch(err) {
      console.log('User sign up failed...' + err);

      if (err.code == 'UsernameExistsException') {
          response["statusCode"] = 409;
      } else if (err.code == 'InvalidPasswordException') {
          response["statusCode"] = 400;
      } else {
          response["statusCode"] = 500;
      }

      return response;
  }
};

感想

とりあえず動くものはできたので一安心。
サインアップは出来たけど確認済みへのステータス変更でエラーになった場合にはリトライで再チャレンジなのか…?
ロールバックがないので工夫は必要である。

今後の宿題

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1