Firebaseではお手軽にログインなどの認証処理を作ることができます。
認証処理では、メールやパスワードの他にも電話番号やGoogle認証、Microsoft認証といった様々な認証方法があります。
この記事では、Reactを使ってFirebaseのWeb認証処理について解説しています。
Firebaseの認証処理とは
Firebaseの認証処理は、Firebase Authenticationのサービスを利用します。
Authenticationでは、FirebaseUIを使用するか、Firebase Authentication SDKを使う2通りの方法があります。
この2つの方法のどちらかを利用して、プロバイダの認証処理を追加します。
ログインで利用できるプロバイダの種類
Firebase Authenticationで利用できるプロバイダには、2種類あります。
1つはネイティブのプロバイダになります。
ネイティブのプロバイダで利用できる認証は、下記になります。
ネイティブのプロバイダ
- メール/パスワード
- 電話番号
- 匿名
もう1つのプロバイダは、GoogleやMicrosoft、Appleなどを利用した認証処理になります。
追加のプロバイダ
- Microsoft
- Apple
- Yahoo
- GitHub
- Play ゲーム
- Game Center
下記は、Firebaseのコンソール画面になります。
ログイン画面を作成する前に
Firebaseで連携する前に、ログイン画面を作成します。
今回は、メールとパスワードのシンプルなフォームにします。
しかし、CSSを利用しないシンプルなフォームだけだと、おもしろくないのでCSSフレームワークを利用します。
Vue.jsやNuxt.jsを利用していた時は、ElementやBulma、Buefyといったフレームワークを使っていました。
でもReactでは、Tailwind CSSが使い勝手や相性が良いそうです。
それでは今回は、Tailwind CSSを使ってログイン画面を構築していきます。
Tailwind CSSとは
ログイン画面を作成する前に、Tailwind CSSとは何なのか説明すると、高度にカスタマイズ可能な低レベルのCSSフレームワークとのことです。
まぁ、コンポーネント化する前提で作られているCSSなので、CSS設計をそこまで意識しなくても良い。
もう少し詳しく知りたい方は、公式サイトをご確認ください。
Tailwind CSSのインストール
Tailwind CSSをインストールするのですが、以前に作成したViteのプロジェクトを利用します。
プロジェクトの作り方が無い方やわからない方は、こちらのViteでプロジェクトを作成する記事をご覧ください。
-
Viteを使ったReact入門
Reactの開発は、IntelliJ IDEAのプラグインを利用して作成していたので特に気にしていませんでした。 しかし、Viteという高速開発を目的としたビルドツールが気になったので、インストールからビルドのやり方について、この記事では解 ...続きを見る
公式にもあるとおり、npmなど介してインストールした方が良いとあるので、npmとyarnの方法を紹介します。
$ npm install tailwindcss
次にyarnによるインストール方法です。
$ yarn add tailwindcss
しかし今回利用しているプロジェクトは、Viteを利用しているので下記のコマンドを利用します。
$ npm install -D tailwindcss postcss autoprefixer
yarnの場合は下記になります。
$ yarn global add tailwindcss postcss autoprefixer
私の場合、上記のyarnコマンドをするとtailwindcssが無いエラーが表示されました。
なので解決策としてグローバルだけではなく、ローカルにもtailwindcssを入れることで解決しました。
$ yarn add tailwindcss
今回はViteを利用していますが、利用しているフレームワークによって、インストール方法が異なります。
そのためVite以外でインストールした方は、このページからフレームワークなどを確認してください。
tailwind.config.jsファイルの作成
Tailwind CSSの設定ファイルを作成します。
ここでもViteを利用していることから、追加したpostcssを利用するため、-pオプションを付けて実行します。
npmでTailwind CSSをインストールした場合は、npxを利用します。
$ npx tailwindcss init -p
yarnでインストールした場合は、下記のコマンドで初期化します。
$ yarn tailwindcss init -p
実行するとプロジェクト直下に、「tailwind.config.js」ファイルが作成されます。
内容は下記になりますが、最初はcontentの部分が空の状態です。
contentの部分にsrcの内容を追加します。
公式では、tsやtsxといったTypeScript用の拡張子も追加されているのですが、使わないので省きます。
module.exports = {
// content: [],
content: ["./src/**/*.{html,js,jsx}"],
theme: {
extend: {},
},
plugins: [],
}
ログイン画面をコーディング
ログインページを作成していきますが、ステップ形式で進めて行きます。
ログイン用のJSXファイルの作成
まずはログインフォームを作成します。
srcディレクトリに、Login.jsxファイルを作成します。
下記が、JSXファイルになりますが、CSSやクラスについては次のステップで装飾していきます。
const Login = () => {
return (
<div className="Login">
<header>
<h1>ログイン画面</h1>
</header>
<main>
<form action="#" method="POST">
<div>
<label htmlFor="email">メールアドレス</label>
<input id="email" name="email" type="email" autoComplete="email" required/>
</div>
<div>
<label htmlFor="password">パスワード</label>
<input id="password" name="password" type="password" autoComplete="current-password" required/>
</div>
<div>
<div>
<a href="#">パスワード忘れた方</a>
</div>
</div>
<div>
<button type="submit">ログイン</button>
</div>
</form>
</main>
</div>
);
}
export default Login;
次に、main.jsxを修正します。
Appタグを読み込んでいる部分をLoginタグに変更します。
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import Login from "./Login"; // AppからLoginに変更
ReactDOM.render(
<React.StrictMode>
<Login /> // AppからLoginに変更
</React.StrictMode>,
document.getElementById('root')
)
これを表示すると、下記の様に表示されます。
シンプルにメールアドレスとパスワードの入力、パスワードを忘れた方へのリンクとログインボタンのページになります。
Tailwind CSSの読み込み設定
HTMLのコーダー部分が終わったので、次にTailwind CSSの読み込み設定を行います。
Tailwind CSSの読み込む設定はsrc/index.cssに書いています。
必ずindex.cssというわけでもなく、別ファイルにして読み込んでも問題ありません。
index.cssの一番上にTailwind CSSを読み込む3行を追加します。
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
・・・省略・・・
表示が変わったかどうか微妙だったので、Login.jsxにあるボタン部分にクラスを追加します。
追加するクラスは、「text-3xl」と「font-bold」です。
これは、テキストサイズとフォントを太文字にするクラスになります。
<button type="submit" className="text-3xl font-bold">ログイン</button>
表示すると入力項目とボタンの部分が変わりました。
スタイルのクラスを埋め込み
Tailwind CSSが反映されたので実際にLogin.jsxを修正します。
修正した結果、下記の様になりました。
import './Login.css'
const Login = () => {
const styleRoot = 'Login container md:3/5 lg:w-3/6 xl:w-2/5 ';
const styleHeader = 'h-20 flex justify-center items-center text-3xl';
const styleMain = 'border border-emerald-400 p-5 rounded-md';
const styleRow = 'p-5 flex flow-root';
const styleInputLabel = 'block pb-1 text-lg text-emerald-700';
const styleInput = 'border rounded-md border-emerald-500 w-full p-2 text-lg text-emerald-900';
const styleBtn = 'p-2 w-full rounded-lg bg-emerald-400 hover:opacity-80 ' +
'text-teal-50 text-lg hover:border-emerald-500 hover:ring-2 font-black';
return (
<div className={styleRoot}>
<header className={styleHeader}>
<h1 className="text-center">ログイン画面</h1>
</header>
<main className={styleMain}>
<form action="#" method="POST">
<div className={styleRow}>
<label htmlFor="email" className={styleInputLabel}>メールアドレス</label>
<input id="email" className={styleInput} name="email"
type="email" autoComplete="email" required/>
</div>
<div className={styleRow}>
<label htmlFor="password" className={styleInputLabel}>パスワード</label>
<input id="password" className={styleInput} name="password"
type="password" autoComplete="current-password" required />
</div>
<div className={styleRow}>
<div>
<a href="#">パスワードを忘れた方</a>
</div>
</div>
<div className={styleRow}>
<button type="submit" className={styleBtn}>ログイン</button>
</div>
</form>
</main>
</div>
);
}
export default Login;
Tailwind CSSの基本は、クラスを使うことです。
なので、classNameに直接クラスを追加していくと可読性が悪くなると思ったので、定数化しました。
正直、下記の様classNameの中で改行するのもアリだと思います。
<div className="border rounded-md border-emerald-500 w-full
p-2 text-lg text-emerald-900">サンプル</div>
この辺は個人的な趣向になりそう。
実際にできたのが、下記の画面になります。
作成していて思ったのですが、Tailwind CSSのドキュメントサイトは開いていた方が良いです。
正直、どういったクラスがあるのかわからないので、下記の赤枠の検索部分をクリックして、colorやsize、flexなどを検索して調べます。
Reactによるログイン画面の処理を追加
ログイン画面ができたので、次はReactの処理を追加していきます。
Reactでは状態管理を行うためにuseStateを利用します。
useStateの追加
まずはReactのuseStateを利用して、メールアドレスとパスワードを取得してみます。
下記の様にuseStateを追加しました。
const [forms, setForms] = useState({});
しかし、ブラウザのコンソール画面を見ると値を入力するたびにWarningが吐かれる。
これはかなり気持ち悪い。
なので、useStateの引数にしっかりとFormタグ内のinputの値を定義した構造で、初期化して入れる。
そうすることで、Warningが無くなります。
const [forms, setForms] = useState({email: '', password: ''});
onChangeイベントの追加
次に、emailとpasswordの部分のsetFormsの処理を追加していきます。
それでは、入力フォームに書き込むとformsの中のデータが更新される処理を作成します。
下記の様に、emailとpasswordの変更があった場合の処理を無名関数で定義します。
const handleEmailChange = e => setForms({...forms, email: e.target.value});
const handlePasswordChange = e => setForms({...forms, password: e.target.value});
カンタンに説明すると、無名関数でsetFormsを利用する。
eの部分が引数なので、setFormsにはformsのデータとe.target.valueでformsの値を更新する。
...formsってなんだ?って思う人がいるかもしれませんが、これはformsにあるデータを展開しています。
これは配列だったりオブジェクトをループ利用することなく追加することができるので、かなり便利です。
配列やオブジェクトのコピーをする場合、これを利用するのが普通になっています。
逆に知らないと損しているので覚えておいた方が良いですね。
それでは次に、各inputにonChangeを記載します。
onChangeはinputなどの入力したデータに変更があった際に発火するイベントです。
このonChnageに入れる値はinputの処理で作成した「handleEmailChange」と「handlePasswordChange」を設定します。
ここでは、emailのinputに対してhandleEmailChangeを設定しています。
<input id="email" className={styleInput} name="email"
type="email" autoComplete="email" required
value={forms.email} onChange={handleEmailChange}/>
パスワードも同じ様にonChangeの中に「handlePasswordChange」を入れます。
<input id="password" className={styleInput} name="password"
type="password" autoComplete="current-password" required
value={forms.password} onChange={handlePasswordChange}/>
onSubmitイベントの追加
buttonタグにonClickイベントをつけても良かったのですが、formタグを利用しているのでonSubmitによる処理にしました。
まずは、formの部分を修正します。
最初は下記の様に書かれていました。
<form action="#" method="POST">
これをactionとmethodを消して、onSubmitを追加します。
<form onSubmit={clickForms}>
次にclickFormsの処理を作ります。
const clickForms = e => {
console.log('buttonが押されました');
e.preventDefault();
};
ここで重要なのはpreventDefault関数になります。
これは、イベントの処理を止める事ができます。
formタグでは、actionのURLに対してmethodのGETやPOSTのリクエストが送信されてページの移動が行われます。
preventDefaultを使うことで、formのリクエストを送るイベントがキャンセルされて送信されることはありません。
動作確認
実際に作成した処理の動作を確認してみます。
その前に、formsの中身がbindされて動いているかも確認したいので、下記のコードをmainタグの上に追加します。
<p>{JSON.stringify(forms)}</p>
<main className={styleMain}>
・・・省略・・・
viteコマンドを使ってローカルサーバを起動して確認します。
$ vite
vite v2.7.13 dev server running at:
> Local: http://localhost:3000/
> Network: use `--host` to expose
ready in 275ms.
起動したら、ブラウザのURLに「http://localhost:3000」を入力すると表示されます。
ちなみにFormタグを利用することで、簡易なバリデーション処理をすることも可能です。
Firebaseとログイン画面の連携
Firebaseとの連携を行うには、Firebase ConsoleからAuthenticationの設定をする必要があります。
設定が完了していたら、アプリケーションの作成になりますが、プラットフォームによってアプリケーションを切り分ける事ができます。
利用できるプラットフォームは下記になります。
プラットフォーム
- iOS
- Android
- WEB
- Unity
Firebase ConsoleからAuthenticationの設定
Firebaseと連携するために、Firebaseのコンソール画面からAuthenticationの設定を行います。
コンソール画面を開いたら、左のメニュにある「Authentication」をクリックします。
すると下記の画面が表示されるので赤枠の「始める」をクリックします。
次にログインプロバイダの選択をしますが、「Sign-in method」のタブが選択されていなければ選択します。
選択すると下記の様にプロバイダを選択する画面が表示されるので、「メール/パスワード」を選択します。
選択すると下記の設定画面が表示されます。
最初は「有効にする」が無効になっているので、赤枠の様に有効します。
有効にしたら「保存」ボタンをクリックして設定完了です。
問題なく有効になっていると下記の様にステータスが有効表示されます。
Firebaseアプリの追加
Firebaseにてアプリの設定を行なっている方は読み飛ばしてください。
アプリが有無に関しては、左メニューのプロジェクトの設定から表示します。
設定画面が表示されると、一番下にマイアプリの項目があります。
アプリが作られていない場合は、今回はWebページなので赤枠のプラットフォームを選択します。
プラットフォームの選択が完了すると下記のウェブアプリの追加画面が表示されます。
ここでアプリ名を入力して「アプリを登録」のボタンをクリックします。
FirebaseのHostingに関しては、このHostingの記事で作成していたので今回はチェックしていません。
Hostingの設定をしていない方は、ご確認ください。
アプリの登録が完了すると下記のSDKのインストール画面が表示されます。
赤枠のconfigの部分が重要でこの値を利用してFirebaseとの連携を行います。
どこかに貼り付けしなくても、確認する事が可能なのでSDKをインストールしていない場合はインストールしてください。
SDKのインストールは、記載されている通りにnpmを使います。
$ npm install firebase --save
ですがyarnを利用している方は、下記にてインストール可能です。
$ yarn add firebase
Reactにenvファイルを作成
React側に環境設定ファイルを作成します。
Reactのプロジェクト直下に.env.localの名称で作成を行い、中のデータはFirebaseのアプリで作成したConfigの値を入れます。
画面を閉じてしまったよって方がいるかもしれませんが、左メニューのプロジェクト概要の隣にある歯車のマークをクリックしてサブメニューが表示されます。
サブメニューのプロジェクトの設定をクリックすると全般の設定が表示されるので、アプリの作成が完了していれば画面下にconfigの設定が表示されます。
項目の名称は自分で決めてください。
私は下記の項目にしました。
FIREBASE_API_KEY=
FIREBASE_AUTH_DOMAIN=
FIREBASE_PROJECTID=
FIREBASE_STORAGE=
FIREBASE_MSG_SENDERID=
FIREBASE_API_ID=
次にFirebaseを利用開始するコードをsrcの中に、Firebase.jsとして作成します。
// Import the functions you need from the SDKs you need
import firebase from "firebase/compat";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
projectId: process.env.FIREBASE_PROJECTID,
storageBucket: process.env.FIREBASE_STORAGE,
messagingSenderId: process.env.FIREBASE_MSG_SENDERID,
appId: process.env.FIREBASE_API_ID
};
// Initialize Firebase
export const auth = firebase.initializeApp(firebaseConfig).auth();
ただこれを動かすと「Uncaught ReferenceError: process is not defined」というエラーが発生します。
このエラーは環境変数が読み込めないエラーになっています。
Viteの環境変数の読み込み方は、processではなくimport.metaを利用する必要があり、環境変数の名称もVITEのプレフィックスをつける必要があります。
そのため、まずは環境変数から修正します。
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECTID=
VITE_FIREBASE_STORAGE=
VITE_FIREBASE_MSG_SENDERID=
VITE_FIREBASE_API_ID=
環境変数を読み込む為に、Viteの開発環境のデフォルト名は「.env.development」にする必要があります。
次にFirebase.jsのソースコードも修正します。
下記の様にprocess.envをimport.meta.envに変更しています。
// Import the functions you need from the SDKs you need
import firebase from "firebase/compat";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
projectId: import.meta.env.VITE_FIREBASE_PROJECTID,
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE,
messagingSenderId: import.meta.env.VITE_FIREBASE_MSG_SENDERID,
appId: import.meta.env.VITE_FIREBASE_API_ID
};
// Initialize Firebase
export const auth = firebase.initializeApp(firebaseConfig).auth();
Viteの環境変数関係は公式サイトのこの記事を参考にしています。
メールとパスワードの認証処理を組み込み
Login.jsxにメールとパスワードによる認証処理を組み込みます。
組み込む場所は、clickFormsに代入した無名関数にsignInWithEmailAndPassword関数を追記します。
認証処理を利用する為にimportします。
上の方に下記のインポート処理を追加しています。
import {auth} from "./Firebase";
次に、signInWithEmailAndPassword関数を組み込みます。
この関数の戻り値はPromiseなので、then・cacthを使用します。
const clickForms = e => {
e.preventDefault();
auth.signInWithEmailAndPassword(forms.email, forms.password)
.then(r => {
console.log(r);
}).catch(e => {
console.log(e);
});
console.log('buttonが押されました');
};
これで認証処理は完了になります。
アカウントの追加
認証処理が完了したので実際にログインをすると下記のエラーが表示されました。
FirebaseError: Firebase: There is no user record corresponding to this identifier. The user may have been deleted. (auth/user-not-found).
at createErrorInternal (assert.ts:122:55)
at _fail (assert.ts:65:9)
at _performFetchWithErrorHandling (index.ts:170:9)
at async _performSignInRequest (index.ts:188:27)
at async _signInWithCredential (credential.ts:37:20)
「Firebase: There is no user record corresponding to this ...」とあるのでアカウント登録のレコードが無いよって書かれています。
そりゃぁ、アカウント登録する処理すら書いていないので当たり前です!
なので追加コードを書こうと思ったのですが、今回はめんどくさいのでFirebaseのコンソール画面から追加します。
左メニューのAuthenticationをクリックして開きます。
すると下記の様にUsersタブの画面が表示されるので、赤枠の「ユーザを追加」からアカウントを登録します。
ボタンをクリックしたら、メールとパスワードを入力する画面が表示されます。
入力して「ユーザーを追加」をクリックして作成します。
追加されると下記の様に表示されます。
再度、作成したアカウントで認証するとコンソール画面に下記の様に表示されます。
失敗すると下記様に返ってきます。
エラー FirebaseError: Firebase: The password is invalid or the user does not have a password. (auth/wrong-password).
at createErrorInternal (assert.ts:122:55)
at _fail (assert.ts:65:9)
at _performFetchWithErrorHandling (index.ts:170:9)
at async _performSignInRequest (index.ts:188:27)
at async _signInWithCredential (credential.ts:37:20)
認証失敗だとエラー内容が「no user record」から「password is invalid 〜」へと変わりました。
Firebaseにデプロイ
ローカル環境にて認証処理が作成できたので、最後の処理としてFirebaseにデプロイします。
しかし、デプロイする前に1つだけ作成するファイルがあります。
それは、本番用の環境変数のファイルになります。
.env.developmentからコピーを行なって、.env.productionを作成します。
今回セキュリティとかも気にしていないのでそのままコピーしていますが、実際にはバックエンドのAPIとかで環境変数の値を隠す様にしてください
Firebaseのデプロイの手順としてまずは、Viteのビルドを行います。
$ vite build
ビルドが完了すると次にFirebaseのデプロイを行います。
$ firebase deploy
単純に上記のコマンドだけでも良いのですが、わかりやすい様に-mオプションを追加して、デプロイと同時にコメントすることも可能です。
$ firebase deploy -m "Firebaseのメールとパスワード認証を追加しました"
まとめ
ReactとTailwind CSSを使ってログイン画面を作成しました。
Tailwind CSSは、CSS設計をほとんど意識することなくウェブアプリを構築していく事が可能です。
Reactと相性も良く、コンポーネントで使用される為に作られたフレームワークになります。
他にもReactとFirebaseの連携では、FirebaseのAuthenticationを利用することでカンタンにメールとパスワードのログイン処理を作成することが可能です。
Viteとcreate-react-appでの環境変数の読み込み方でハマった部分はありますが、同じ様なことでハマった人への参考になればと思います。
-
ViteのReactを使ってFirebase フェデレーションIDプロバイダのログイン処理について解説
GoogleアカウントやFacebookアカウントなどを利用したログイン処理を作成するのは、Firebaseを利用するとカンタンに実装することができます。 この記事では、ViteのReactを使ったプロバイダのログイン方法を解説しています。 ...続きを見る
今後の人生を豊かにする為にキャリアアップのステップとして、自分への投資をしてみませんか?