こんにちは、 wand です!
このブログは AWS 上に自分で構築したものです。
以前、このブログの開発環境に Lambda@Edge と Cognito を使った認証の実装方法をご紹介しました。
当時は Cognito のユーザー名・パスワードでログインしていましたが、再ログインのたびに入力が必要で、不便に感じていました。
今回は Cognito と「Googleでログイン」(Sign in with Google) を連携し、Google アカウントで手軽にログインできるようにします!
設定を行うにあたり、思わぬ落とし穴もありますので、試す場合は斜め読みせず、最後まで読んでからお試しください!
対象読者
- Web アプリケーションに Amazon Cognito + 「Google でログイン」 で認証を実装したい
- Google 個人アカウントで「Google でログイン」を実現したい
Amazon Cognito と 「Googleでログイン」の連携概要
Cognito のみで認証を行う場合、Cognito ユーザープールでユーザー情報を直接管理します。
一方、 Cognito と「Googleでログイン」を連携する場合は、ユーザー情報は Google 側で管理され、Cognito 側には「外部 ID」として登録される形になります。この仕組みを ID フェデレーションといいます。
Cognito と Google の間で ID フェデレーションを実現するには、 Open ID Connect (OIDC) というプロトコルを使用します。
(OIDC とは、認可プロトコルである OAuth 2.0 をベースに認証も可能にした拡張仕様です。)
ここからは、以下の順に OIDC の設定手順を解説します。
- Amazon Cognito の仮設定
- Google の OAuth 2.0 クライアントの設定
- Amazon Cognito の本設定
Amazon Cognito の仮設定
Cognito 側と Google 側で互いの設定情報が必要なので、最初はどちらかを仮設定して作業を進めます。
ここでは Cognito を仮設定し、まずは Cognito でアプリケーションにログインができるところまで設定しましょう。
以下の記事で解説しています!
後で使用するため、Cognito のログインページの URL を控えておきましょう。
Google OAuth 2.0 クライアントの設定
Google Cloud コンソールで OAuth 2.0 の設定を行います。

「APIとサービス」を選択します。

続いて、「OAuth 同意画面」を選択します。

この画面では、以下の3つの設定を行います。
- クライアント
- 対象
- データアクセス
説明をわかりやすくするため、画面上の順序から変更しています。
クライアント
ここで OAuth 2.0 クライアントを作成します。「どのアプリケーションにログインできるか」を設定するものです。

今回は Web アプリケーションに認証をかけるため、「アプリケーションの種類」は「ウェブ アプリケーション」を選択します。
名前は任意のものをつけましょう。
次に、 Cognito の URL を2つ設定します。

- 「承認済みの JavaScript 生成元」に Cognito のログインページの URL を設定します。
- 「承認済みのリダイレクト URI 」には、 Cognito の仕様上、
<Cognito のログインページのURL>/oauth2/idpresponse
を設定します。
OAuth 2.0 クライアントを作成すると、クライアントシークレットをダウンロードできます。

{
"web": {
"client_id": "...",
"client_secret": "...",
// ...
}
}
この client_id
と client_secret
を後で使用します。
対象
ここでは、「誰がアクセス可能か」を決める認可設定を行います。

「公開ステータス」が「テスト中」、「ユーザーの種類」が「外部」となっていることを確認します。
個人アカウントでは「外部」のみ選択可能です。
Google Workspace アカウントの場合は「内部」が選択可能です。
今回のユースケースは「ブログの開発環境を自分だけに公開する」ことですので、「テスト中」のままにしておきます。
続いて、「テストユーザー」に自分の Google アカウントのメールアドレスを追加します。

公開ステータスが「テスト中」に設定されている間は、テストユーザーのみがアプリにアクセスできます。
とあります。一見、「テストユーザーに制限をかけたから安心!」と思いがちですが…
この設定だけでは Google アカウントを持つ誰でもログインできてしまいます!
この問題は、次の「データアクセス」の設定で解決します。
データアクセス
OAuth 2.0 の認可スコープを設定します。ここでは、「何にアクセスしてよいか」を決める認可設定を行います。

Google のサポートドキュメントによると、
Google will display a warning message before allowing a specified test user to authorize scopes requested by your project's OAuth clients.
...
The only exception to this behavior is if your app requests a subset of the following: name, email address, and user profile (through the userinfo.email, userinfo.profile, openid scopes or their OpenID Connect equivalents). For such requests, your users do not need to be in the trusted user list, ...
とあります。つまり…
email , profile , openid 以外の認可スコープを追加しないと、テストユーザー以外にもアプリケーションが公開されてしまいます!
上記以外の認可スコープを 1 つ追加しましょう。

今回は https://www.googleapis.com/auth/tagmanager.readonly
を追加しました。

email
, profile
, openid
, tagmanager.readonly
を選択し、「更新」します。
以上で Google 側の設定は完了です。
Amazon Cognito の本設定
AWS インフラは SAM (Serverless Application Model) を用いてコード化しています。
GitHub でコードを公開していますので、参考にしてください。
今回追加・変更する箇所は以下の通りです。
# ...
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Condition: UseAccessControl
Properties:
# ...
SupportedIdentityProviders:
- !Ref CognitoUserPoolIdentityProvider
# ...
CognitoUserPoolIdentityProvider:
Type: AWS::Cognito::UserPoolIdentityProvider
Condition: UseAccessControl
Properties:
AttributeMapping:
email: email
username: sub
IdpIdentifiers: []
ProviderDetails:
authorize_scopes: !Join
- " "
- - profile
- email
- openid
# NOTE: profile, email openid 以外の何か「認可」にまつわるスコープを含めないとアクセス制御が効かない!
# テストユーザー以外にも、 Google アカウントを持つ人全員に公開されてしまう
# see: https://support.google.com/cloud/answer/15549945?hl=en#zippy=%2Ctesting
- https://www.googleapis.com/auth/tagmanager.readonly
client_id: !Sub "{{resolve:ssm:/${AWS::StackName}-oauth2/client-id}}"
# NOTE: SecureString 非対応
client_secret: !Sub "{{resolve:ssm:/${AWS::StackName}-oauth2/client-secret}}"
ProviderName: Google
ProviderType: Google
UserPoolId: !Ref CognitoUserPool
CognitoUserPoolIdentityProvider
リソースを追加し、 CognitoUserPoolClient
の SupportedIdentityProviders
で参照します。
これにより、認証方式が「Google でログイン」に切り替わります。
以下では CognitoUserPoolIdentityProvider
リソースの設定の詳細を説明します。
Google OAuth 2.0 クライアント ID / シークレットの設定
client_id: !Sub "{{resolve:ssm:/${AWS::StackName}-oauth2/client-id}}"
# NOTE: SecureString 非対応
client_secret: !Sub "{{resolve:ssm:/${AWS::StackName}-oauth2/client-secret}}"
Google OAuth 2.0 クライアントの client_id
と client_secret
を設定します。
ソースコードへのハードコーティングを避けるため、 SSM Parameter Store の動的参照を使用しています。

事前に SSM Parameter Store にパラメータを作成し、設定値を格納しておき、 {{resolve:ssm:/path/to/param}}
という形式で参照します。
動的参照の文字列を !Sub 等で組み立てることも可能です。
なお、本来であれば SecureString を使うべき場面ですが、 AWS::Cognito::UserPoolIdentityProvider
の client_secret
は SecureString の動的参照に対応していません。
Error: Failed to create changeset for the stack: blog-stg, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expressi
on "Status" we matched expected path: "FAILED" Status: FAILED. Reason: SSM Secure reference is not supported in: [AWS::Cognito::UserPoolIdentityProvider/Properties/ProviderDetails/client_secret,AWS::Cognito::UserPoolIdentityProvider/Properties/ProviderDetails/client_id]
別の方法として、 AWS Secrets Manager のシークレットを利用することも可能ですが、シークレット 1 つあたり 0.4USD/月 のコストが発生します。
そのため、今回は無料で利用できる SSM Parameter Store のプレーンテキスト String を使用することにしました。
Google OAuth 2.0 の認可スコープ設定
authorize_scopes: !Join
- " "
- - profile
- email
- openid
# NOTE: profile, email openid 以外の何か「認可」にまつわるスコープを含めないとアクセス制御が効かない!
# テストユーザー以外にも、 Google アカウントを持つ人全員に公開されてしまう
# see: https://support.google.com/cloud/answer/15549945?hl=en#zippy=%2Ctesting
- https://www.googleapis.com/auth/tagmanager.readonly
前述のとおり、profile, email, openid のみではアクセス制御が機能せず、誰でもログインできる状態になってしまいます!
そのため、 Google 側の「データアクセス」で設定した認可スコープを、ここでも定義する必要があります。
今回は https://www.googleapis.com/auth/tagmanager.readonly
を含めます。
以上で AWS 側の設定は完了です。最後に、Cognito と「Googleでログイン」を連携した認証の動作確認を行います。
動作確認

アプリケーションにアクセスすると、 「Google でログイン」のページにリダイレクトします。

自分の Google アカウントでログインすると、アプリケーションにアクセスできました!

また、別の Google アカウントではアクセスが拒否されることも確認でき、期待どおりの動作になっています。
まとめ
Cognito と「Google でログイン」を連携することで、Google アカウントを使ってスムーズにログインできるようになりました。
毎回ユーザー名・パスワードを入力する手間もなくなり、認証の利便性が向上します。
特に、Google アカウントを活用した認証の導入を検討している場合、Cognito との連携は有力な選択肢となるでしょう。
認証を実装する際は、導入を検討してみてはいかがでしょうか?