AWSReact

React x Amplify(Gen2) x CognitoでさくっとGoogle認証を実装してみる

公開日:2024-10-14 更新日:2024-10-14

今回はReact x Amplifyでアプリをデプロイし、Google認証を実装する手順についてまとめていきます。

React プロジェクトの作成

Viteを使ってReactプロジェクトを作ります。

npm create vite@latest my-react-app -- --template react-ts

起動確認をします。

cd my-react-app
npm install
npm run dev

http://localhost:5173/

アクセスしてロゴが表示されていることを確認します。

必要なパッケージをインストールします。

npm install --save-dev @aws-amplify/backend@latest @aws-amplify/backend-cli@latest

Amplifyプロジェクトの作成

続いて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-react

amplify/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認証と連携する

続いて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ユーザープールの更新

続いて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 sandbox

AWSマネジメントコンソールから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

参考

Twitter Share