Next.js(App Router)×TypeScriptで
FirebaseのAuthenticationを使ってGoogleログイン認証を実装した時の手順。

ちなみに「メール認証」編はこちら👇
目次
前提
- Next.js:プロジェクト作成済み
- Firebase : プロジェクト作成済み
- フォームのUI:実装済み
Firebase AuthenticationでGoogle認証を実装する方法
アプリ追加〜初期化まですでに実施済みの場合は、ログインとログアウト機能を実装するまでスキップ🏃♀️💨
Firebaseでアプリを追加
プロジェクトの設定>全般タブ から「アプリの追加」をクリック。
下記は左から3つ目を選択。(今回はWebアプリなので)

手順通りに進め、上記を実施。
※うろ覚えなので次回実施時に修正するかも。firebase init
含めそれ以降は実施不要。
.env.localに必要情報を記述
上記を行うと下記の値が表示されるので.env.local
に記述する
NEXT_PUBLIC_FIREBASE_API_KEY="xxxxxxx"
FIREBASE_AUTH_DOMAIN="xxxxxxx.firebaseapp.com"
FIREBASE_PROJECT_ID="xxxxxxx"
FIREBASE_STORAGE_BUCKET="xxxxxxx.firebasestorage.app"
FIREBASE_MEASUREMENT_ID="xxxxxxx"
FIREBASE_SENDER_ID="xxxxxxx"
FIREBASE_APP_ID="xxxxxxx"
FIREBASE_API_KEYだけ”NEXT_PUBLIC_”をつけている理由
クライアントサイドでAPI KEYの値が参照できず、下記エラーとなるため。
FirebaseError: Firebase: Error (auth/invalid-api-key).
✍️その他の変数も、クライアントサイドで利用する場合は適宜NEXT_PUBLIC_
を付与する。
✍️ただしNEXT_PUBLIC_
をつけた環境変数はクライアント (ブラウザ) にも送信され、誰でも見れる状態になる。機密情報 (APIキーやDB接続情報など) を含む環境変数には使わないこと。
Firebase を初期化する
service/firebase.js
import { initializeApp } from 'firebase/app';
import { getAuth, signInWithPopup, GoogleAuthProvider, signOut } from "firebase/auth";
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
ログインとログアウト機能を実装する
service/firebase.js
に下記を追記
export const auth = getAuth(app);
export const db = getFirestore(app);
export const provider = new GoogleAuthProvider();
export const signInWithGoogle = () => {
signInWithPopup(auth, provider).then((result) => {
console.log(result);
});
};
export const signOutWithGoogle = () => {
auth.signOut();
};
ログインボタンを実装する
components/auth/GoogleLogin.tsx
に下記を記述
※ router.push("/");
でログイン後のリダイレクト先を設定
"use client";
import Image from 'next/image'
import { signInWithGoogle } from '../../service/firebase'
import { useRouter } from 'next/navigation';
function GoogleLogin() {
const router = useRouter();
const handleSignIn = async () => {
await signInWithGoogle();
router.push("/");
};
return (
<button onClick={handleSignIn}>
<Image src={"/img/web_light_rd_SU@2x.png"} alt={"Googleでログインする"} width={358} height={80} />
</button>
)
}
export default GoogleLogin
ログアウトボタンを実装する
components/auth/Logout.tsx に下記を記述
※ router.push("/login");
でログアウト後のリダイレクト先を設定
"use client";
import { signOutWithGoogle } from '@/service/firebase';
import { useRouter } from 'next/navigation';
import React from 'react'
function Logout() {
const router = useRouter();
const handleSignOut = async () => {
await signOutWithGoogle();
router.push("/login");
};
return (
<button onClick={handleSignOut}>ログアウト</button>
)
}
export default Logout
ログイン・ログアウト状態を判定し、表示分けをする※
react-firebase-hooks をインストール
npm i react-firebase-hooks
ログインしている時だけフッターコンポーネントを表示するコードはこんな感じになる。
※ useAuthState
はクライアントサイドでしか使えない
"use client"
import Footer from '@/components/layout/Footer';
import { auth } from '@/service/firebase';
import React, { ReactNode } from 'react'
import { useAuthState } from 'react-firebase-hooks/auth';
function AsyncLayout({ children }: { children: ReactNode }) {
const [user] = useAuthState(auth); // ログイン判定
const containerClassName = user ? "login" : "logout"
return (
<>
<div className={containerClassName}>
{children}
{ user ? <Footer /> : "" }
</div>
</>
)
}
export default AsyncLayout
※【追記】この方法だとクライアントサイドでしか使えないようなので、サーバサイドでもログイン管理するためには他の手段の検討が必要そう・・・なので、このやり方は却下になるかも?
まだそこまで実装が進んでいないので、のちほど検討したいと思います・・・!
以上です!