AWS-Amplify

AmplifyでCognitoの認証画面をカスタマイズする(React)

AmplifyでCognitoの認証画面をカスタマイズする(React)

こんにちは。
SRE課の栩野です。

前回に続きAmplify+Cognitoネタ第二弾です。

AmplifyでCognitoを作成した時、デフォルトでは
以下のような認証画面になっています。

文言が英語で、不要な入力項目があったり...
実際にこのまま利用するには、ちょっと厳しいです。

そこで、今回は認証画面を以下のような形にカスタマイズして
いこうと思います。

▼サインイン

▼サインアップ

▼パスワードリセット

▼パスワードリセット変更

Cognitoのカスタマイズ

ではでは、早速カスタマイズしていきます。

今回以下の内容をいじっていきます。

  • 文言の日本語化
  • 不要な入力項目の削除
  • デザインの変更

そのほか追加として...

  • サインアウトボタンのカスタマイズ
  • 全体のコード
  • 推奨設定の紹介

準備しておくこと

デフォルト状態のReactプロジェクトにAmplifyで
Cognitoを実装している前提で進めていきます。

まだの方は是非前回のブログを参考にしてください。

AmplifyでCognitoによる認証画面を実装する(React)

実行環境

  • Amplify CLI 5.3.0
  • yarn 1.22.5

手順

認証画面のカスタマイズは基本的に以下のドキュメントを参考にしています。
Amplify Authenticatorドキュメント

文言のカスタマイズと日本語化

デフォルトの文言をカスタマイズするには
各コンポーネントのpropsに設定したい文言を渡していきます。

例えば、サインイン画面の文言を変更する場合は
AmplifySignInのコンポーネントを追加して
以下参考にpropsとして日本語の文言を渡していきます。

import logo from "./logo.svg";
import "./App.css";

// AmplifySignInをimport
import { AmplifyAuthenticator, AmplifySignIn } from "@aws-amplify/ui-react";

import Amplify from "aws-amplify";
import awsconfig from "./aws-exports";

Amplify.configure(awsconfig);

// AmplifyAuthenticator内にAmplifySignInを追加し
// 以下参考に文言を渡していく
function App() {
  return (
    <AmplifyAuthenticator>
      <AmplifySignIn
        slot="sign-in"
        headerText="サインイン画面"
        submitButtonText="サインイン"
        formFields={[
          {
            type: "username",
            label: "サインインID *",
            placeholder: "ユーザ名を入力",
            required: true,
          },
          {
            type: "password",
            label: "パスワード *",
            placeholder: "パスワードを入力",
            required: true,
          },
        ]}
      />
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
            Learn React
          </a>
        </header>
      </div>
    </AmplifyAuthenticator>
  );
}

export default App;

headerTextがタイトル、submitButtonTextがボタン
formFieldsでフォームの各項目を設定しています。

これで指定した箇所が日本語になりました。

コンポーネント毎で設定できるpropsについては
ドキュメントをご参照ください。
Amplify Authenticatorドキュメント

ただ、どうしても日本語に出来ない箇所があるので
そのような箇所は、英語と日本語を紐づける辞書を作成して対処します。

以下のような形で、英語と日本語を紐づけた辞書を作成します。
サインイン画面で日本語に出来なかった文言の辞書を作成してみます。

// I18nをimportする
import { I18n } from "aws-amplify";

// 以下のような形で日本語と英語を紐づけた辞書を作成する
const dict = {
  ja: {
    "Forgot your password?": "パスワードを忘れた場合",
    "Reset password": "パスワードをリセット",
    "No account?": "アカウントを持っていない場合",
    "Create account": "サインアップ",
  },
};

// 作成した辞書を渡して反映させる
I18n.putVocabularies(dict);
I18n.setLanguage("ja");

とりあえずは、App.jsx内に上記のコードを記載すると
いい感じに文言が置き換わりました!

手軽なので文言は全部これで置き換えてもよさそうですね。
詳しくは以下のドキュメントを参考にしてください。

Amplifyの日本語化ドキュメント

不要な入力項目の削除 (電話番号)

サインアップする際に、電話番号の入力であったり
不要な項目の入力が求められるため
フォームから電話番号の項目を削除します。

サインアップのフォームに必要な項目だけを記載することで
電話番号の入力項目を除外できます。

      // AmplifySignUpをimportして以下設定
      <AmplifySignUp
        slot="sign-up"
        headerText="サインアップ"
        haveAccountText=""
        signInText="サインインに戻る"
        submitButtonText="アカウント作成"

        // formFields内に必要な項目だけを指定することで
        // 電話番号を除外できる
        formFields={[
          {
            type: "username",
            label: "ユーザ名を入力してください",
            placeholder: "ユーザ名",
          },
          {
            type: "email",
            label: "メールアドレスを入力してください",
            placeholder: "メールアドレス",
          },
          {
            type: "password",
            label: "パスワードを入力してください",
            placeholder: "パスワード",
            inputProps: { required: true, autocomplete: "new-password" },
          },
        ]}
      />

これでユーザ名、アドレス、パスワードの入力だけになりました!

デザインの変更

デフォルトではオレンジ色のボタンを赤色に変更してみます。
以下のような形でCSSを設定します。

/* とりあえず全部赤で */
:root {
  --amplify-primary-color: #c53030;
  --amplify-primary-tint: #c53030;
  --amplify-primary-shade: #c53030;
}

これでボタンの色が変わりました。

CSSの設定については、Amplifyのドキュメントを確認して変更
もしくは、ブラウザの検証ツールでプロパティ名を確認して
自力で変更する形で対応できます。

サインアウトボタンのカスタマイズ

サインアウトのボタンはデフォルトでは以下のような見た目になっています。
(App.jsxにAmplifySignOutを埋め込んだだけの状態)

文言などはサインイン画面と同じ要領で変更できますが
見た目そのものをカスタマイズしたい場合は、自作のボタンを作成して
onClickで「Auth.SignUp」を呼び出すことでカスタマイズしたサインアウトボタン
を実装できます。

とりあえずbuttonタグにonClickで設定してみます。

// 以下import
import { Auth } from "aws-amplify";

// AmplifySignOutの部分を以下置き換え
<button onClick={() => Auth.signOut()}>サインアウト</button>

これでサインアウトボタンをカスタマイズ出来ました。

後はお好みでCSSを設定してカスタマイズしてください。

全体のコード

最初に紹介した認証画面の全体のコードは以下になります。
(App.jsxに全部詰め込んでます)

import logo from "./logo.svg";
import "./App.css";

import {
  AmplifyAuthenticator,
  AmplifySignIn,
  AmplifyForgotPassword,
  AmplifySignUp,
  AmplifySignOut,
  AmplifyConfirmSignUp,
  AmplifyRequireNewPassword,
} from "@aws-amplify/ui-react";
import { Auth, I18n } from "aws-amplify";
import Amplify from "aws-amplify";
import awsconfig from "./aws-exports";

Amplify.configure(awsconfig);

const dict = {
  ja: {
    "Forgot your password?": "パスワードを忘れた場合",
    "Reset password": "パスワードをリセット",
    "No account?": "アカウントを持っていない場合",
    "Create account": "サインアップ",
    "Back to Sign In": "サインインに戻る",
    "Username *": "ユーザ名 *",
    "Enter your username": "ユーザ名を入力",
    "Confirmation Code": "確認コード",
    "Enter your code": "確認コードを入力",
    "Lost your code?": "確認コードが届かない場合",
    "Resend Code": "再送する",
    "Verification code": "検証コード",
    "Enter code": "検証コードを入力",
    "New password": "新しいパスワード",
    "Enter your new password": "新しいパスワードを入力",
  },
};

I18n.putVocabularies(dict);
I18n.setLanguage("ja");

function App() {
  return (
    <AmplifyAuthenticator>
      <AmplifySignIn
        slot="sign-in"
        headerText="サインイン画面"
        submitButtonText="サインイン"
        formFields={[
          {
            type: "username",
            label: "サインインID *",
            placeholder: "ユーザ名を入力",
            required: true,
          },
          {
            type: "password",
            label: "パスワード *",
            placeholder: "パスワードを入力",
            required: true,
          },
        ]}
      />
      <AmplifyForgotPassword
        slot="forgot-password"
        headerText="パスワードを忘れた"
        usernameAlias="email"
        formFields={[
          {
            type: "username",
            label: "ユーザ名を入力してください",
            placeholder: "ユーザ名",
          },
        ]}
        sendButtonText="送信"
        submitButtonText="送信"
      />
      <AmplifySignUp
        slot="sign-up"
        headerText="サインアップ"
        haveAccountText=""
        signInText="サインインに戻る"
        submitButtonText="アカウント作成"
        formFields={[
          {
            type: "username",
            label: "ユーザ名を入力してください",
            placeholder: "ユーザ名",
          },
          {
            type: "email",
            label: "メールアドレスを入力してください",
            placeholder: "メールアドレス",
          },
          {
            type: "password",
            label: "パスワードを入力してください",
            placeholder: "パスワード",
            inputProps: { required: true, autocomplete: "new-password" },
          },
        ]}
      />
      <AmplifyRequireNewPassword
        headerText="新しいパスワードを入力"
        submitButtonText="送信"
        slot="require-new-password"
      />
      <AmplifyConfirmSignUp headerText="確認コードを入力してください" submitButtonText="送信" slot="confirm-sign-up" />
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <AmplifySignOut />
          <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
            Learn React
          </a>
          <button onClick={() => Auth.signOut()}>サインアウト</button>
        </header>
      </div>
    </AmplifyAuthenticator>
  );
}

export default App;

推奨設定の紹介

今回はAmplifyAuthenticatorで認証したい部分を囲んで使いましたが
推奨される使い方としては、条件式でサインインの有無をみて
表示するページを分けるような方法が推奨されているようです。

推奨される使用方法

以下サンプルのコードを置いておきます。

import React from 'react';
import './App.css';
import Amplify from 'aws-amplify';
import { AmplifyAuthenticator, AmplifySignOut } from '@aws-amplify/ui-react';
import { AuthState, onAuthUIStateChange } from '@aws-amplify/ui-components';
import awsconfig from './aws-exports';

Amplify.configure(awsconfig);

const AuthStateApp = () => {
    const [authState, setAuthState] = React.useState();
    const [user, setUser] = React.useState();

    React.useEffect(() => {
        return onAuthUIStateChange((nextAuthState, authData) => {
            setAuthState(nextAuthState);
            setUser(authData)
        });
    }, []);

  // AuthStateをみて、認証済みなら前者、未認証なら後者の認証画面を表示
  return authState === AuthState.SignedIn && user ? (
      <div className="App">
          <div>Hello, {user.username}</div>
          <AmplifySignOut />
      </div>
    ) : (
      <AmplifyAuthenticator />
  );
}

export default AuthStateApp;

その他にも「withAuthenticator」を使った設定方法など
詳しく知りたい方はドキュメントをご確認ください。

あとがき

このような形で手軽に文言や見た目のカスタマイズできました。
以上、最後までありがとうございました!

参考

AmplifyでCognitoによる認証画面を実装する(React)
Amplify Authenticatorドキュメント
Amplifyの日本語化ドキュメント

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA