3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Laravel + Amazon Cognito】で、ユーザー新規登録を試したまとめ

Last updated at Posted at 2019-12-28

laravel_cognito(qiita).png

前提条件(環境)

2019年12月28日に試してみたものです。
Laravel 5.8
aws/aws-sdk-php 3.13

期待する動作

登録フォームにメールとパスワードを入力して送信すると、Cognitoのユーザープールに仮登録される。
そして、その際に届いたメールのリンクを辿ると、「アカウントのステータス」が「CONFIRMED」になる。

手順

  1. IAMで、Cognitoにアクセス可能なアクセスキー作成
  2. Cognito側の初期設定
  3. AWSのSDKをインストール
  4. AWSの情報を.envファイルに追加
  5. SDKの中にある、CognitoIdentityProviderClientクラスに用意されているsignUpメソッドを使う

1. IAMで、Cognitoにアクセスできるアクセスキー作成

割愛

2. Cognito側の初期設定

  1. 「ユーザープールの作成」
  2. 「デフォルトを確認する」
  3. アプリクライアントの作成

デフォルトと変えた部分は以下4つ

  • ユーザーのサインインに使う項目:Eメールアドレス
  • カスタム属性custom:hogeを追加
  • Eメールの検証タイプを「コード」から「リンク」に変更 → Cognito ドメインの作成or自己所有ドメインの登録が必要
  • アプリクライアント:「クライアントシークレットを生成」のチェックを外した

注意

  • 「クライアントシークレットを生成」にチェックを入れると、SDKのCognitoIdentityProviderClientクラスの色々なメソッドの引数として、シークレットキーが必須になってくる。
  • デフォルトのパスワードの強度は、強すぎるので注意

ユーザーの属性について

  • 必須の標準属性と、後から追加できるカスタム属性がある。
  • 標準属性は、email,genderなど17個の中から選ぶことができるが、ユーザープール作成後は変更できない。
  • カスタム属性は、名前を自由に決めることができるが、名前の先頭に勝手にcustom:が付けられる。また、ユーザープール作成後に追加できるが、削除はできない。

カスタム属性について

  • 試しにユーザーをプールに追加した後に、カスタム属性を追加してみたが、その場合でも、カスタム属性追加前のユーザーに、追加したカスタム属性の値を登録することができた。
  • ユーザープール作成後にカスタム属性を追加した場合、デフォルトのアプリクライアントでは、カスタム属性の読み込み権限や書き込み権限が付与されていない
    アプリクライアント画面の「属性の読み込みおよび書き込みアクセス権限を設定する」で変更できる。

3. AWSのSDKをインストール

これで、CognitoのAPIにアクセスできるメソッド等をvendor内にインストールできる

$ composer require aws/aws-sdk-php

4. AWSの情報を.envファイルに追加

.env
# AWS(IAM)
AWS_ACCESS_KEY_ID==(IAMユーザーのアクセスキーID)
AWS_SECRET_ACCESS_KEY=(IAMユーザーのシークレットアクセスキー)

# AWS(Cognito)
AWS_DEFAULT_REGION=(ユーザープールを作成したリージョン)
AWS_COGNITO_VERSION=2016-04-18
AWS_COGNITO_USER_POOL_ID=(プールID)
AWS_COGNITO_APP_CLIENT_ID=(アプリクライアントID)

5.CognitoIdentityProviderClientクラスのsignUpメソッドを使う

  • CognitoのAPIにアクセスするためのクライアントを実装
  • 下記URLに、CognitoIdentityProviderClientクラスのメソッドの一覧があり、それぞれ引数や返り値等が書かれている。

  • signUpメソッドの必須の引数は3つ(ClientId、Password、Username)。必須の標準属性を設定した場合には、そのUserAttributesも必須。「クライアントシークレットを生成」にチェックを入れている場合、SecretHashも必須
app/Cognito/CognitoClient.php
<?php

namespace App\Cognito;

// SDKの中から使うクラス
use Aws\CognitoIdentityProvider\CognitoIdentityProviderClient;
use Aws\CognitoIdentityProvider\Exception\CognitoIdentityProviderException;

class CognitoClient
{
    protected $client;
    protected $clientId;
    protected $poolId;

    public function __construct(CognitoIdentityProviderClient $client, $clientId, $poolId)
    {
        $this->client = $client;
        $this->clientId = $clientId;
        $this->poolId = $poolId;
    }

    public function register($email, $password, array $attributes = [])
    {
        $attributes['email'] = $email;

        try {
            //CognitoIdentityProviderClientクラスのsignUpメソッド
            $response = $this->client->signUp([
                'ClientId' => $this->clientId,
                'Password' => $password,
                'UserAttributes' => $this->formatAttributes($attributes),
                'Username' => $email,
            ]);

        } catch (CognitoIdentityProviderException $e) {
            throw $e;
        }

        return;
    }

    protected function formatAttributes(array $attributes)
    {
        $userAttributes = [];
        foreach ($attributes as $key => $value) {
            $userAttributes[] = [
                'Name' => $key,
                'Value' => $value,
            ];
        }
        return $userAttributes;
    }
}

6 その他のソースコード

あえてGuardは使わず、できるだけシンプルにしました。

ルーティング

routes/web.php
// 登録フォーム
Route::get('/register', "RegisterController@registerForm")->name('authRegister');
Route::post('/register', "RegisterController@temporaryRegister");

ビュー1つ

resources/views/auth/register_form.blade.php
{{-- フラッシュメッセージ --}}
@if (session('temporary_register'))
<div class="alert alert-success">
    {{ session('temporary_register') }}
</div>
@endif

{{-- 登録フォーム --}}
<div>
    <form action="{{ route('authRegister') }}" method="post">
        @csrf
        <input type="email" name="email">
        <input type="password" name="password">
        <input type="submit" value="新規登録する">
    </form>
</div>

Cognito用のServiceProvider

app/Providers/CognitoAuthServiceProvider.php
<?php

namespace App\Providers;

use App\Cognito\CognitoClient;
use Aws\CognitoIdentityProvider\CognitoIdentityProviderClient;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;

class CognitoAuthServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // .envファイルに書いた認証情報と、CognitoClientの結合
        $this->app->singleton(CognitoClient::class, function (Application $app) {
            
            $config = [
                'region' => env('AWS_DEFAULT_REGION'),
                'version' => env('AWS_COGNITO_VERSION'),
            ];

            return new CognitoClient(
                new CognitoIdentityProviderClient($config),
                env('AWS_COGNITO_APP_CLIENT_ID'),
                env('AWS_COGNITO_USER_POOL_ID')
            );
        });
    }
}

作成したServiceProvierの登録を忘れないように!

app/config/app.php
// 中略

'providers' => [
        // 中略
        
        App\Providers\CognitoAuthServiceProvider::class, // <- 追加
];

Controller

app/Http/Controllers/RegisterController.php
<?php

namespace App\Http\Controllers;

use App\Cognito\CognitoClient;
use Illuminate\Http\Request;

class RegisterController extends Controller
{
    public function registerForm()
    {
        return view("auth.register_form");
    }

    public function temporaryRegister(Request $request)
    {
        // 属性
        $attributes = ['custom:hoge' => "テスト"];
        // CognitoClientクラスに書いたregisterメソッドを使う
        app()->make(CognitoClient::class)->register($request->email, $request->password, $attributes);

        return redirect()->route('authRegister')->with('temporary_register', 'まだ仮登録です。メールに記載されたリンクにアクセスして下さい');
    }
}

その他:パスワードリセット・変更等のメソッド

メソッド
パスワードリセット ForgotPassword
パスワード変更 ChangePassword
属性の変更 UpdateUserAttributes
退会 DeleteUser

これらは全て、AccessTokenが必須の引数となっている。
AccessTokenは、InitiateAuth(又はAdminInitiateAuth)メソッドの返り値として取得できる。

参照:https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.CognitoIdentityProvider.CognitoIdentityProviderClient.html

参考にさせて頂いた記事

Laravel + AWS Cognito での認証機能の実装【ユーザー新規登録編】
[Laravelのユーザ認証をAmazon Cognitoで行う方法]
(https://qiita.com/suzumurakk/items/efe4543cf0df2cd31659)

3
5
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
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?