目的
CognitoでGoogleアカウントとFacebookアカウントを紐づけることで、メールアドレスが同一なら同一ユーザであると識別する。
ユーザプール設定
まずはAWSコンソール上で全ての設定をデフォルトでユーザプールを作成します。
その後、IDプロバイダーの設定でFacebook・Googleを追加します。
追加の方法はこちらのページで詳しく説明されています。
設定し終わると以下のような設定になります。
その後、アプリクライアントの設定タブで有効なIDプロバイダにチェックを入れ、コールバックURLの設定をします。
一番下にあるホストされたUIを起動をクリックすると以下の画面が現れます。
Google・Facebookそれぞれのアカウントでログインして以下のことが確認できれば設定は完了です。
- ちゃんとコールバックする
- ユーザとグループタグでユーザが作成されている
実装
以下が実際に試したコードの一部になります。
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の状態が以下の画面です。