今回はReact x Amplifyでアプリをデプロイし、Google認証を実装する手順についてまとめていきます。
Viteを使ってReactプロジェクトを作ります。
npm create vite@latest my-react-app -- --template react-ts起動確認をします。
cd my-react-app
npm install
npm run devアクセスしてロゴが表示されていることを確認します。

必要なパッケージをインストールします。
npm install --save-dev @aws-amplify/backend@latest @aws-amplify/backend-cli@latest続いてProjectのrootディレクトリにbackend amplifyプロジェクトを立ち上げます。
npm create amplify@latest
>>>
> my-react-app@0.0.0 npx
> create-amplify
? Where should we create your project? .
Installing devDependencies:
- @aws-amplify/backend
- @aws-amplify/backend-cli
- aws-cdk@^2
- aws-cdk-lib@^2
- constructs@^10.0.0
- typescript@^5.0.0
- tsx
- esbuild
Installing dependencies:
- aws-amplify
⠧ Installing devDependenciesこのコマンドにより新たにディレクトリができあがります。
├── amplify/
│ ├── auth/
│ │ └── resource.ts
│ ├── data/
│ │ └── resource.ts
│ ├── backend.ts
│ └── package.json理屈はあまり分かっていないのですが、デプロイ時にCloudformationと連携してawsのバックエンドリソースを立ち上げるのに用いられていそうです。authディレクトリはCognitoのリソース作成に、dataディレクトリはDynamoDBを用いる場合に記述をしていくディレクトリみたいです。
今回は認証だけ行いたいので、dataディレクトリは 使いません。削除しましょう。
├── amplify/
│ ├── auth/
│ │ └── resource.ts
│ ├── backend.ts
│ └── package.jsonこのようになりました。
まずはemailとパスワードを利用した通常ログインを実装してみましょう。
今回は非常に簡単にCognitoと連携が行える@aws-amplify/ui-reactを利用します。
npm install @aws-amplify/ui-reactamplify/backend.tsを編集します。といっても削除したdataの記述を消すだけです。以下のようにしましょう。
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
/**
* @see https://docs.amplify.aws/react/build-a-backend/ to add storage, functions, and more
*/
defineBackend({
auth,
});
続いて、記述した内容をsandbox環境に反映させます。
npx ampx sandbox
>>>
[Sandbox] Watching for file changes...
File written: amplify_outputs.json以上のようにメッセージが出ましたら、Ctr + Cで終了させましょう。
amplify_outputs.jsonが生成されます。
{
"auth": {
"user_pool_id": "ap-northeast-1_poolid",
"aws_region": "ap-northeast-1",
"user_pool_client_id": "cognito_client_id",
"identity_pool_id": "ap-northeast-1:identity_pool_id",
"mfa_methods": [],
"standard_required_attributes": [
"email"
],
"username_attributes": [
"email"
],
"user_verification_types": [
"email"
],
"mfa_configuration": "NONE",
"password_policy": {
"min_length": 8,
"require_lowercase": true,
"require_numbers": true,
"require_symbols": true,
"require_uppercase": true
},
"unauthenticated_identities_enabled": true
},
"version": "1.2"
}AWSマネジメントコンソールに行くと、Cognitoのユーザープールが作成されているかと思います。

続いてメインのコードを修正していきましょう。まずはsrc/main.tsxでAmplifyを有効化してReactアプリを開始します。
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import '@aws-amplify/ui-react/styles.css'
import { Amplify } from 'aws-amplify'
import outputs from '../amplify_outputs.json'
Amplify.configure(outputs)
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)続いてsrc/app.tsxを以下のようにします。
import './App.css'
import { Authenticator } from '@aws-amplify/ui-react'
function App() {
return (
<Authenticator>
{({ signOut, user }) => (
<>
<div>
<h1>{user?.username}!</h1>
<p>認証されました</p>
<button
onClick={signOut}
>
Sign Out
</button>
</div>
</>
)}
</Authenticator>
)
}
export default App
npm run devすると、以下のようなログイン画面が立ち上がります。

Create Accountしてみましょう。

メールでコードが届くので、入力してサインアップします。

Cognitoにユーザー登録がされ、認証が行われたことが分かります。

続いてGoogle側の設定をしていきましょう。
基本的にはAmplifyの公式手順に沿って行っていきます。
https://docs.amplify.aws/react/build-a-backend/auth/concepts/external-identity-providers/
まずはGoogle developer console.にアクセスをします。
プロジェクトの選択からプロジェクトを作成をします。

次の画面で適当にMy Amplify Projectのようなプロジェクトを登録します。
左ペインの認証情報から認証情報を作成をクリックします。OAuth クライアント ID を選択します。

続いての画面で「OAuth クライアント ID を作成するには、まず同意画面で設定を行う必要があります」と出てくるので同意画面に遷移します。
日本語が怪しい気がしますが、気にせずにつづけます。
外部を選択します。

続いての画面でアプリ名を聞かれますので、適当に入力します。
メールアドレスは自分のアドレスを入れましょう。

他必須じゃないところは空欄でいいです。
進めるとテストユーザーを追加するボタンが出現するので、自分のメールアドレスを指定します。

追加したらOAuth クライアント IDの作成に戻ります。

承認済みの JavaScript 生成元と承認済みのリダイレクト URIは本来はCognitoのDomainに即したURLを入れますが、現時点ではCognitoのDomainは生成されていないので、一旦はhttps://www.example.comのような適当な値を入れて作成します。
クライアントIDとクライアントSECRETが発行されるので、メモしておきましょう。
続いてCognitoをGoogleでログインできるように更新しておきます。
amplify/auth/resource.tsを以下のようにします。
import { defineAuth, secret } from '@aws-amplify/backend';
/**
* Define and configure your auth resource
* @see https://docs.amplify.aws/gen2/build-a-backend/auth
*/
export const auth = defineAuth({
loginWith: {
email: true,
externalProviders: {
google: {
clientId: secret('GOOGLE_CLIENT_ID'),
clientSecret: secret('GOOGLE_CLIENT_SECRET'),
scopes: ['email']
},
callbackUrls: [
'http://localhost:5173/',
],
logoutUrls: ['http://localhost:5173/'],
}
},
});
次に先ほどメモしたGOOGLE_CLIENT_IDとGOOGLE_CLIENT_SECRETを環境変数に反映させます。
npx ampx sandbox secret set GOOGLE_CLIENT_ID
npx ampx sandbox secret set GOOGLE_CLIENT_SECRET再びSandbox環境に反映をさせます。
npx ampx sandboxAWSマネジメントコンソールからCognitoに行きますとドメインが発行されています。

再びGoogleに戻ってドメインに即したURLを入力します。
承認済みの JavaScript 生成元:https://your-domain.auth.ap-northeast-1.amazoncognito.com
承認済みのリダイレクト URI:https://your-domain.auth.ap-northeast-1.amazoncognito.com/oauth2/idpresponse
続いてsrc/App.tsxのSocial Providerにgoogleを指定します。
import './App.css'
import { Authenticator } from '@aws-amplify/ui-react'
function App() {
return (
<Authenticator socialProviders={['google']}>
{({ signOut, user }) => (
<>
<div>
<h1>{user?.username}!</h1>
<p>認証されました</p>
<button
onClick={signOut}
>
Sign Out
</button>
</div>
</>
)}
</Authenticator>
)
}
export default App
npm run devして立ち上げると、よくあるGoogleログインリンクが表示され、ユーザーの作成、ログインが行えるはずです。

続いて本番へのデプロイを行っていきましょう。
まずはgithubにソースコードをpushします。Privateで構いません。
続いてAmplifyにアクセスしてGithubベースでアプリを作成します。

先ほどpushしたリポジトリを指定します。

そのまま、デフォルトの設定のままデプロイをします。

デプロイが始まります。
一定時間が経過するとデプロイが失敗します。
2024-10-14T11:03:33.044Z [INFO]: SecretNotSetError: The secret 'GOOGLE_CLIENT_ID' specified in the backend does not exist.SECRETの設定が必要とのことです。
サイドペインのホスティングよりシークレットの編集をします。

GOOGLE_CLIENT_IDとGOOGLE_CLIENT_SECRETを設定して保存します。

保存したら再デプロイをして数分待ちますと…デプロイが完了しました!

URLにアクセスするとローカルのログインページが表示されています。

ただしGoogleでサインインしようとするとエラーになります。

これはcallbackとlogoutのURL設定が本番用にされていないためです。
amplify/auth/resource.tsを更新してgit pushしましょう。
import { defineAuth, secret } from '@aws-amplify/backend';
/**
* Define and configure your auth resource
* @see https://docs.amplify.aws/gen2/build-a-backend/auth
*/
export const auth = defineAuth({
loginWith: {
email: true,
externalProviders: {
google: {
clientId: secret('GOOGLE_CLIENT_ID'),
clientSecret: secret('GOOGLE_CLIENT_SECRET'),
scopes: ['email']
},
callbackUrls: [
'http://localhost:5173/',
// 追記
'https://master.d2gqzvqcw33vpq.amplifyapp.com/'
],
logoutUrls: [
'http://localhost:5173/',
//追記
'https://master.d2gqzvqcw33vpq.amplifyapp.com/'
],
},
},
});
自動でデプロイが走りこれでいけるか?と思いログインをすると、Googleさんに怒られました。
アクセスをブロック: このアプリのリクエストは無効ですこれはリダイレクトURLの設定が間違っているときにおこるらしいです。
Cognitoを確認すると先ほどのSandbox版とは別に本番用のユーザープールができています。

そのため、Googleの設定を置き換える必要があります。
承認済みの JavaScript 生成元と承認済みのリダイレクト URIを本番用のCognitoのドメインで置き換えて保存します。
本番URLでGoogleでサインインできることを確認して終了です。

すこしつまづいたところもありましたが、よくある認証機能をコードの記述なしで作成できるので、ぱっと何か作りたい時に向いていると思いました。
ソースコードはgithubに公開していますので、ご参照ください。
https://github.com/qlitre/react-amplify-cognito-gen2