LoginSignup
0
0

More than 1 year has passed since last update.

【Firebase】Firebase Authentication メール&Google認証の実装(後編)【React】

Last updated at Posted at 2023-01-11

はじめに

ハマりそうだった原神放置中です、こんにちは。
早速以前投稿した記事の続きを書きたいと思います。

前回のおさらい

◆前回の記事

◆前回の目的
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ログイン画面だけを作る
・公式ドキュメントより下記を追加

firebase.js
//追加
import { GoogleAuthProvider } from "firebase/auth";

const provider = new GoogleAuthProvider();

ログイン処理に、signInWithPopupではなく、signInWithRedirectを利用する
公式ドキュメントを参考にコードを書いてく

Login.js
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ログインで作ったページにメールアドレスログインフォームも追加する

Login.js
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;
Home.js
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認証の実装ができた。
前編で取り組んでいたアクセス制限設定は次回以降に回します。
以上メモ代わりでした。ありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0