1
0

More than 1 year has passed since last update.

【個人開発】WEBサービスのログイン機能をAWS Cognitoで実装する①

Last updated at Posted at 2023-03-02

要件

  • サービスのログイン機能をAWSマネージドサービスである AWS Cognitoを使用して実装する。

  • 認証にはユーザID、Eメールアドレスを使用する。

  • サインアップ時、Eメールアドレスに検証メッセージを送信する。

  • パスワード要件

    • 最小文字数を6文字とする。
    • 少なくとも1つの数字、大文字、小文字を使用する。
  • 以下の情報をユーザに持たせる。

    • ユーザID
    • Eメールアドレス
    • 誕生日
    • ニックネーム
    • URL 

AWS 設定

CloudFormation (cognito構築部分のみ)

CF_congnito.yaml
  MyMovieUserPool:
    Type: AWS::Cognito::UserPool
    Properties: 
      AliasAttributes: 
        - email
      AutoVerifiedAttributes: 
        - email
      Policies: 
        PasswordPolicy: 
          MinimumLength: 6
          RequireLowercase: true
          RequireNumbers: true
          RequireUppercase: true
      Schema: 
        - AttributeDataType: "String"
          Name: "birthdate"
          Required: true
        - AttributeDataType: "String"
          Name: "email"
          Required: true
        - AttributeDataType: "String"
          Mutable: true
          Name: "preferred_username"
          Required: true
        - AttributeDataType: "String"
          Mutable: true
          Name: "website"
          Required: true
      UsernameConfiguration: 
        CaseSensitive: false
      UserPoolName: !Sub mymovie-${EnviromentType}-userpool

  MyMovieUserPoolAppClient:
    Type: AWS::Cognito::UserPoolClient
    Properties: 
      ClientName: MyMovie
      EnableTokenRevocation: false
      PreventUserExistenceErrors: ENABLED
      ExplicitAuthFlows:
        - ALLOW_ADMIN_USER_PASSWORD_AUTH
        - ALLOW_USER_PASSWORD_AUTH
        - ALLOW_USER_SRP_AUTH
        - ALLOW_REFRESH_TOKEN_AUTH
      UserPoolId: !Ref MyMovieUserPool

Signup画面(html)

※以下の例では、jquery,bootstrapを利用しています。

signup.html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <!-- viewport meta -->
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Required bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
    <!-- Required cognito -->
    <script src="js/cognito/jsbn.js"></script>
    <script src="js/cognito/jsbn2.js"></script>
    <script src="js/cognito/sjcl.js"></script>
    <script src="js/cognito/aws-sdk.min.js"></script>
    <script src="js/cognito/aws-cognito-sdk.min.js"></script>
    <script src="js/cognito/amazon-cognito-identity.min.js"></script>
    <!-- Required jquery -->
    <script src="js/jquery-3.6.0.min.js"></script>
    <!-- Required js/css -->
    <script src="js/signin.js"></script>
  </head>
  <body>
<!-- サインインフォーム -->
      <div id="signup" class="container-fluid w-75 p-3">
        <h1>Sign Up</h1>
        <div id="message"><span style="color: red;"></span></div>
            <form name="form-signup">
                <br><div class="row mb-3">
                <label class="col-sm-2 col-form-label">User ID</label>
                <div class="col-sm-10">
                    <input class="form-control" id="username" placeholder="User ID(半角英数記号のみ)">
                </div>
                </div>
                <br><div class="row mb-3">
                <label class="col-sm-2 col-form-label">Email</label>
                <div class="col-sm-10">
                    <input class="form-control" id="email" placeholder="Email Address">
                </div>
                </div>
                <br><div class="row mb-3">
                  <label class="col-sm-2 col-form-label">NickName</label>
                <div class="col-sm-10">
                    <input class="form-control" id="name" placeholder="Name">
                </div>
                </div>
                <br>
                <div class="row mb-3">
                  <label class="col-sm-2 col-form-label">Birthdate</label>
                  <div class="col-sm-10">
                    <div class="row">
                      <div class="col">
                        <!-- <input type="number" class="form-control" value="2020" aria-label="year" id="year"> -->
                        <select type="number" class="form-control" aria-label="year" id="year">
                        </select>
                      </div>
                      <div class="col">
                        <!-- <input type="number" class="form-control" value="01" aria-label="month" id="month"> -->
                        <select type="number" class="form-control" value="month" aria-label="month" id="month">
                          <option>01</option>
                          <option>02</option>
                          <option>03</option>
                          <option>04</option>
                          <option>05</option>
                          <option>06</option>
                          <option>07</option>
                          <option>08</option>
                          <option>09</option>
                          <option>10</option>
                          <option>11</option>
                          <option>12</option>
                        </select> 
                      </div>
                      <div class="col">
                        <!-- <input type="number" class="form-control" value="01" aria-label="day" id="day"> -->
                        <select type="number" class="form-control" value="day" aria-label="day" id="day">
                        </select>
                      </div>
                    </div>
                  </div>
                </div>
                  <br><div class="row mb-3">
                    <label class="col-sm-2 col-form-label">Password</label>
                  <div class="col-sm-10">
                    <input class="form-control" type="password" id="password" placeholder="Password(英大/小文字/数字必須 6文字以上)">
                  </div>
                  </div>
                  <br>
                <button type="button" class="btn btn-primary" id="createAccount">Create Account</button>
            </form>
      </div>
    </div>
  </body>
</html>

Signupロジック(JavaScript)

signup.js
// ユーザープールの設定
var user_pool_id = "{USER_POOL_ID}"
var client_id = "{CLIENT_ID}"
const poolData = {
  UserPoolId : user_pool_id,
  ClientId : client_id
};
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var attributeList = [];

$(function() {
  // 「Create Account」ボタン押下時
  $("#createAccount").click(function(event) {
  //エラーメッセージ表記初期化
  $("#signup div#message span").empty();
  signUp();
  });
});

// サインアップ処理。
var signUp = function() {
  var username = $("#username").val();
  var email = $("#email").val();
  var name = $("#name").val();
  //誕生日
  var year = $("#year").val();
  var month = $("#month").val();
  var day = $("#day").val();
  var birthdate = year + "-" + month + "-" + day

  var sns = $("#sns").val();
  var password = $("#password").val();

    //空欄チェック
    if (!username | !email | !name | !birthdate | !password) { 
      $("#signup div#message span").append("項目に入力漏れがあります");
      return false;
    }

    //nameの長さチェック
    if (username.length >= 16 || name >= 16) {
      $("#signup div#message span").append("User ID / NickName は16文字までです");
      return false;
    }

    //nameの中身チェック
    var vaildname = /^[a-zA-Z0-9!-/:-@¥[-`{-~]+$/;
    if(!vaildname.test(username)){
      $("#signup div#message span").append("User ID が正しくありません");
      return false;
    }

    //メールアドレスチェック
    var vaildemail = /^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]+.[A-Za-z0-9]+$/;
    if(!vaildemail.test(email)){
      $("#signup div#message span").append("メールアドレスが正しくありません");
      return false;
    }

    //パスワード判定
    var vaildpassword = isValidPassword(password)
    if(!vaildpassword){
      $("#signup div#message span").append("パスワードが正しくありません(英大/小文字/数字を入れた6文字以上)");
      return false;
    }

    // ユーザ属性リストの生成
    var dataEmail = {
      Name : "email",
      Value : email
    }

    var dataName = {
      Name : "preferred_username",
      Value : name
    }

    var dataSNS = {
      Name : "website",
      Value : sns
    }

    var dataBirthdate = {
      Name : "birthdate",
      Value : birthdate
    }

    var attributeEmail = new AmazonCognitoIdentity.CognitoUserAttribute(dataEmail);
    var attributeName = new AmazonCognitoIdentity.CognitoUserAttribute(dataName);
    var attributeSNS = new AmazonCognitoIdentity.CognitoUserAttribute(dataSNS);
    var attributeBirthdate = new AmazonCognitoIdentity.CognitoUserAttribute(dataBirthdate);

    attributeList.push(attributeEmail);
    attributeList.push(attributeName);
    attributeList.push(attributeSNS);
    attributeList.push(attributeBirthdate);
    
    // サインアップ処理
    userPool.signUp(username, password, attributeList, null, function(err, result){
      if (err) {
        $("#signup div#message span").append(err.message);
      return;
      } else {
        window.location.href = './activation.html';
      }
    });  
    .catch(error => {
      $("#signup div#message span").append("登録情報の送信に失敗しました");
    });
}

※activation、signin処理は次の記事に続きます。
https://qiita.com/haruya_hamasaki/items/92d5972e46768a902104

参考

おまけ

本記事の機能は以下のサービスで利用されています。
気になった方は、お気軽にサービスも利用くださると大変嬉しいです。

観た映画を登録、管理できるサービス MyMovie

映画一覧.png

サービスURL : mymovie.jp
GitHub : github.com/hamasakiharuya/mymovie

1
0
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
0