はじめに
ハマりそうだった原神放置中です、こんにちは。
早速以前投稿した記事の続きを書きたいと思います。
前回のおさらい
◆前回の記事
◆前回の目的
FirebaseAuthentication+Reactで
2種類のサインアップ(メール、Google)を実装する
◆前回の結果
- メール認証→OK
- Google認証→YET
- 作業中にnpmのトラブルに見舞われて中断
今回の目指すところ
- FirebaseAuthenticationにGoogle認証の実装
前提
環境・構成ディレクトリ
前回と変わりません
◆環境
Windows10
Firebase 9.15
React 18.2
Node.js 18.12.1
◆ディレクトリ構成(Ralacodeさんに準拠)
[src]
├─[components]
| ├ Home.js
| ├ Login.js
| ├ Register.js
| ├ PrivateRoute.js
| └ PublicRoute.js
├─[context]
| └ AuthContext.js
├─App.js
├─App.css
├─firebase.js
└─Page404.js
基本参考サイト(チュートリアル先)
この分かりやすい2つのサイトを見比べながら構築しました
他ちょこちょこみたサイト
作業内容
Google認証
前回の記事でメール認証はクリアできたのでGoogle認証にとりかかる。
まずしたこと
・Googleログイン画面だけを作る
・公式ドキュメントより下記を追加
//追加
import { GoogleAuthProvider } from "firebase/auth";
const provider = new GoogleAuthProvider();
ログイン処理に、signInWithPopupではなく、signInWithRedirectを利用する
公式ドキュメントを参考にコードを書いてく
import { provider } from '../firebase';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { getAuth, signInWithRedirect } from "firebase/auth";
import { getRedirectResult, GoogleAuthProvider } from "firebase/auth";
const auth = getAuth();
getRedirectResult(auth)
.then((result) => {
// This gives you a Google Access Token. You can use it to access Google APIs.
const credential = GoogleAuthProvider.credentialFromResult(result);
const token =
credential.accessToken;
// The signed-in user info.
const user = result.user;
}).catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
// The email of the user's account used.
const email = error.customData.email;
// The AuthCredential type that was used.
const credential = GoogleAuthProvider.credentialFromError(error);
// ...
});
const Login = () => {
const navigate = useNavigate();
const [error, setError] = useState('');
const handleLogin = async (event) => {
try {
signInWithRedirect(auth, provider);
navigate('/');
} catch (error) {
console.log(error);
setError(error.message);
}
};
return (
<div>
<h1>ログイン</h1>
{error && <p style={{ color: 'red' }}>{error}</p>}
<button onClick={handleLogin}>Googleログイン</button>
</div>
);
};
export default Login;
とりあえずGoogleでログインができた。
ページ遷移もstateされていて問題ない模様。
これからGoogleログインで作ったページにメールアドレスログインフォームも追加する
import { provider } from '../firebase';
import { useNavigate } from 'react-router-dom';
import { useState, useEffect } from 'react';
import { getAuth, signInWithRedirect } from "firebase/auth";
import { getRedirectResult, GoogleAuthProvider } from "firebase/auth";
import { Navigate, Link } from "react-router-dom";
import {signInWithEmailAndPassword, onAuthStateChanged } from "firebase/auth";
const auth = getAuth();
getRedirectResult(auth)
.then((result) => {
// This gives you a Google Access Token. You can use it to access Google APIs.
const credential = GoogleAuthProvider.credentialFromResult(result);
const token =
credential.accessToken;
// The signed-in user info.
const user = result.user;
}).catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
// The email of the user's account used.
const email = error.customData.email;
// The AuthCredential type that was used.
const credential = GoogleAuthProvider.credentialFromError(error);
// ...
});
const Login = () => {
const navigate = useNavigate();
const [error, setError] = useState('');
const handleLogin = async (e) => {
try {
signInWithRedirect(auth, provider);
navigate('/');
} catch (error) {
console.log(error);
setError(error.message);
}
};
const [loginEmail, setLoginEmail] = useState("");
const [loginPassword, setLoginPassword] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
try {
await signInWithEmailAndPassword(
auth,
loginEmail,
loginPassword
);
} catch (error) {
alert("メールアドレスまたはパスワードが間違っています");
}
};
const [user, setUser] = useState();
useEffect(() => {
onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
});
return (
<>
<h1>ログイン</h1>
<p>ログイン方法を選択してください</p>
{error && <p style={{ color: 'red' }}>{error}</p>}
<button onClick={handleLogin}>Googleログイン</button><br /><br />
{user ? (
<Navigate to={`/`} />
) : (
<>
<form onSubmit={handleSubmit}>
<div>
<label>メールアドレス</label>
<input
name="email"
type="email"
value={loginEmail}
onChange={(e) => setLoginEmail(e.target.value)}
/>
</div>
<div>
<label>パスワード</label>
<input
name="password"
type="password"
value={loginPassword}
onChange={(e) => setLoginPassword(e.target.value)}
/>
</div>
<button>メールログイン</button>
<p>新規登録は<Link to={`/register/`}>こちら</Link></p>
</form>
</>
)}
</>
);
};
export default Login;
import React, { useState, useEffect } from "react";
import { onAuthStateChanged, signOut } from "firebase/auth";
import { auth } from "../firebase.js";
import { useNavigate, Navigate } from "react-router-dom";
const Home = () => {
const [user, setUser] = useState("");
const [loading, setLoading] = useState(true);
useEffect(() => {
onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
setLoading(false);
});
}, []);
const navigate = useNavigate();
const logout = async () => {
await signOut(auth);
navigate("/login/");
}
return (
<>
{!loading && (
<>
{!user ? (
<Navigate to={`/login/`} />
) : (
<>
<h1>マイページ</h1>
<p>{user?.email}</p>
<button onClick={logout}>ログアウト</button>
</>
)}
</>
)}
</>
);
};
export default Home;
GoogleAuthentication使用時のちょくちょく出たエラーメッセージ
Unable to process request due to missing initial state. This may happen if browser sessionStorage is inaccessible or accidentally cleared.
ググるとFirebaseサイドの問題と出てきたので一旦放置
さいごに
これでFirebaseAuthenticationにメールとGoogle認証の実装ができた。
前編で取り組んでいたアクセス制限設定は次回以降に回します。
以上メモ代わりでした。ありがとうございました。