雰囲気データサイエンティストの備忘録

Atmosphere Data Scientist's Memorandum


AmplifyでGoogleIdP認証付きのアプリをデプロイする
AWS

概要

Amplifyで認証を入れたときのメモ。

バックエンドサーバーの構築,ローカルでのテスト

amplify authの設定

以下を参考に,認証を組み込んでいきます。
https://docs.amplify.aws/javascript/build-a-backend/auth/add-social-provider/https://docs.amplify.aws/javascript/build-a-backend/auth/add-social-provider/

amplify add auth

以下のようにサインアウト・サインインの後のリダイレクト先を設定する項目があります。とりあえずはローカルで動かすとして,localhostを設定しておきます。(Amplifyでホスティングするときには修正が必要になります。)

...
? Enter your redirect signin URI:
    `http://localhost:3000/`
? Enter your redirect signout URI:
    `http://localhost:3000/`

ひとしきりの質問に答えることで,Amplifyの構成ファイルがローカルに作成されます。これを以下コマンドでAWSに送信します。

amplify push

このコマンドを叩くと裏でCloudFormationが動きます。構成が完了すると,以下のようなエンドポイントが表示されます。

Hosted UI Endpoint: https://{アプリ名とランダムな文字列}-dev.auth.{region}.amazoncognito.com

このURLをGCPの"APIとサービス">"認証情報">"OAuth 2.0 クライアント ID"の
"Authorized Javascript origin"に貼り付けます。
同様に"Authorized Redirect URIs"には,URLの末尾に/oauth2/idpresponseをつけて貼り付けます。

ログインアプリの作成

以下のようなログイン・ログアウトだけのシンプルなコンポーネントを作成します。

loginboard.tsx
import { Amplify } from 'aws-amplify';
import { Authenticator, AccountSettings } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

import awsmobile from '../src/aws-exports.js';
Amplify.configure(awsmobile);

const LoginBoard = () => {
    const handleSuccess = () => {
        alert('user has been successfully deleted')
    }
    return (
        <>
            <Authenticator socialProviders={['google']}>
                {({ signOut, user }) => (
                    <main>
                        <button onClick={signOut} className='underline'>
                            サインアウト
                        </button>
                        <div>
                            <>
                                ここにログインユーザーにしか見えないコンテンツを入れる
                            </>
                            <AccountSettings.DeleteUser />
                        </div>
                    </main>
                )}
            </Authenticator>
        </>
    )
}

export default LoginBoard

重要なのは以下の部分です。

import awsmobile from '../src/aws-exports.js';
Amplify.configure(awsmobile);

aws-exports.jsというファイルにcognitoの認証情報が書き込まれており,これをもとにしてAmplifyに構成ファイルを渡します。そうすると,Authenticator, AccountSettingsなどのコンポーネントが認証の確認先を認識することができるようになります。

ローカルでの動作チェック

yarn devでテストサーバーを立てて,試しにGoogleサインインしてみます。
ログイン前
signin

ログイン後 
content

ログインできていれば,Cognitoのユーザープールにユーザーが追加されているのが確認できます。
"DeleteUser"のボタンでアカウント削除も可能です。

Amplifyでのホスティング

ビルド

amplifyにgithubのブランチを登録します。

バックエンド環境を選ぶところは,先ほど作ったバックエンドの名前を差すようにします。サービスロールはamplifyconsole-backend-roleを選択します。

自動でブランチの内容を読み取って,サーバーのビルド設定amplify.ymlを生成してくれます。自分の環境だととりあえずこのままでもビルドが通りました。

version: 1
backend:
  phases:
    build:
      commands:
        - '# Execute Amplify CLI with the helper script'
        - amplifyPush --simple
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn run build
  artifacts:
    baseDirectory: .next
    files:
      - '**/*'
  cache:
    paths:
      - .next/cache/**/*
      - node_modules/**/*

backend側でamplifyPush --simpleと書いているのがミソになっています。
立ち上がった直後のサーバーはgithubからコードをcloneしただけの状態で,cognitoなどのサービスとの接続情報を持っていません。そのため,amplifyPushコマンドが必要になります。

実行するとビルドが始まり,サーバーの更新が完了するまで待ちます。完了するとAmplifyが以下のようなURLを発行してくれるので,サイトにアクセスできます。
https://{ブランチ名}.{ランダムな文字列}.amplifyapp.com/

サイト内の静的ページには問題なくアクセスできますが,Google認証しようとするとエラーが出て失敗します。

エラー対応

userpoolにリダイレクトURLを追加する

先ほどはリダイレクトURLにlocalhostだけを設定していましたが,発行されたURLを追加します。
ついでに,特定のドメインを取得している場合はそれも追加します。

amplify auth update

以下のように聞かれるところで,リダイレクトURLを編集するように答えます。

 What do you want to do? 
    >Add/Edit signin and signout redirect URIs
    ...
    # 以下を追加する。
      https://www.example.com/  # カスタムドメイン
      https://{ブランチ名}.{ランダムな文字列}.amplifyapp.com/  # amplifyで生成されたURL

カスタムドメインは当初https://example.com/を入れていたのですが,wwwをつけないとエラーが出るようでした。

リダイレクト先を環境により書き換える

loginboard.tsxを編集します。

以下のように,awsmobileredirectSignInまたはredirectSignOutを実行環境によって書き換えるようにします。

loginboard.tsx
// 環境によってリダイレクト先を変更
if (typeof window !== "undefined") {
    awsmobile.oauth.redirectSignIn = `${window.location.origin}/`;
    awsmobile.oauth.redirectSignOut = `${window.location.origin}/`;
}
Amplify.configure(awsmobile);

備考

ログインユーザーの権限

amplify authをpushした際に,amplify... authRole,またはamplify... unauthRoleというIAMロールが作成されています。authRoleがログインユーザーのロール,unauthRoleがゲストユーザーに与えられている権限になります。
この辺りの情報はAWS内のリソースに対してAPIを実行する際に重要になります。