3
4

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 3 years have passed since last update.

CognitoでGoogleアカウントとFacebookアカウントを紐づける

Last updated at Posted at 2020-03-26

目的

CognitoでGoogleアカウントとFacebookアカウントを紐づけることで、メールアドレスが同一なら同一ユーザであると識別する。

ユーザプール設定

まずはAWSコンソール上で全ての設定をデフォルトでユーザプールを作成します。
その後、IDプロバイダーの設定でFacebook・Googleを追加します。
追加の方法はこちらのページで詳しく説明されています。
設定し終わると以下のような設定になります。
ユーザープール_-_Amazon_Cognito.png
ユーザープール_-_Amazon_Cognito.png

その後、アプリクライアントの設定タブで有効なIDプロバイダにチェックを入れ、コールバックURLの設定をします。
ユーザープール_-_Amazon_Cognito.png
一番下にあるホストされたUIを起動をクリックすると以下の画面が現れます。
Signin.png
Google・Facebookそれぞれのアカウントでログインして以下のことが確認できれば設定は完了です。

  • ちゃんとコールバックする
  • ユーザとグループタグでユーザが作成されている

ユーザープール_-_Amazon_Cognito.png

実装

以下が実際に試したコードの一部になります。

    public function snsSignIn(string $authorizationCode) // コールバックで受け取った code
    {
        $signInResponse = $this->cognito->snsSignIn($authorizationCode); // ※1
        try {
            // DB の中に Cognito のユーザネームが保存されていればログイン、なければ 404 になります
            $this->authentication->login($signInResponse->getCognitoTokens());
        } catch (\Exception $exception) {
            if ($exception->getCode() !== 404) {
                throw $exception;
            }

            $accessToken = $signInResponse->getAccessToken();
            $socialUser = $this->cognito->fetchUserInfo($accessToken); // ※2
            $cognitoUsername = $socialUser['email'];
            $socialAccountUsername = $socialUser['username'];

            try {
                $cognitoUser = $this->cognito->adminGetUser($cognitoUsername); // ※3
                $cognitoId = $cognitoUser['Username'];
            } catch (Exceptions\UserNotFoundException $exception) {
                // Cognitoアカウントを作成し、ステータスを CONFIRM にする。
                $createResponse = $this->cognito->createUser($cognitoUsername);
                $this->cognito->adminSetUserPassword($cognitoUsername);
                $cognitoId = $createResponse->getCognitoId();
                // TODO DB に Cognito ユーザネームを登録
            }

            // Status が EXTERNAL_PROVIDERであるソーシャルアカウントを削除
            $this->cognito->adminDeleteUser($socialAccountUsername); // ※4

            // Cognitoアカウントとソーシャルアカウントをリンク
            $this->cognito->linkProviderForUser($cognitoId, $socialAccountUsername); // ※5
        }
        $this->accessTokenHandler->setUserPool($this->cognito);
        return route('HomeIndex');
    }

※1 トークンエンドポイント
※2 USERINFO エンドポイント
※3 AdminGetUser
※4 AdminDeleteUser
※5 AdminLinkProviderForUser

注意すべき点は※4の部分です。
linkProviderForUserはソーシャルアカウントと既存のユーザを紐づけることができますが、紐づけたいソーシャルアカウントが既にEXTERNAL_PROVIDERでアカウントが生成されている場合は以下のエラーが出てしまいます。
Merging is not currently supported, provide a SourceUser that has not been signed up in order to link

そのためリンクする前にEXTERNAL_PROVIDERのアカウントを削除しています。

上記のコードを使用し、FacebookとGoogleアカウントでログインしたあとのCognitoの状態が以下の画面です。

アカウントが一つだけ存在します。
ユーザープール_-_Amazon_Cognito.png

中身を見てみるとIdentitiesにGoogleとFacebookのアカウントが登録されていることがわかります。
ユーザープール_-_Amazon_Cognito.png

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?