🔐

【Next.js × Firebase】Authenticationで爆速Googleログイン実装

2024/06/16に公開

はじめに

前回はfirebaseのサービスfirestoreを使ってDB構築を行いました。今回は同じくfirebaseのサービスのAuthenticationを使ってGoogleログインを導入します。

Firebaseセットアップ

前回の記事で紹介したので省略します。

Authenticationセットアップ

Authenticationを選択>始める

プロバイダーを選択(今回はGoogleを選択)

有効にする>メールアドレス入力>保存

以上で完了です。簡単...

Firebase+Authentication初期化処理

Next.jsの記述に移ります。

config情報はプロジェクトの設定に記載されているものを環境変数で管理しています。

lib/firebase.ts
import { initializeApp } from "firebase/app";
import { GoogleAuthProvider, getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: process.env.FIREBASE_APIKEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STRAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MASSAGING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID,
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Cloud Firestore and get a reference to the service
export const db = getFirestore(app);

export const auth = getAuth(app);
export const provider = new GoogleAuthProvider();

SignInコンポーネント作成

SignInコンポーネントはログイン状態を見てサインインボタンかログアウトボタンを出し分ける役割をしています。
コンポーネントに切り出した理由としては後ほど紹介するGoogleサインインの関数(signInWithPopup)はクライアントコンポーネントでしか使用できず"use client"の記述をしているためです。(ちなみにNext.js v14 app Routerを使用しています。)
このコンポーネントを親のサーバーコンポーネントでimportして使います。

SignIn.tsx
"use client";
import { auth, provider } from "@/lib/firebase/firebase";
import { signInWithPopup } from "firebase/auth";
import { useRouter } from "next/navigation";
import React from "react";
import { useAuthState } from "react-firebase-hooks/auth";

export const SighIn = () => {
  const [user] = useAuthState(auth);
  const router = useRouter();

  const signInWithGoogle = () => {
    signInWithPopup(auth, provider).then((result) => {
      console.log(result);
      router.push("/tasks");
    });
  };

  const signOutWithGoogle = () => {
    auth.signOut();
  };

  return (
    <>
      {user ? (
        <button
          onClick={signOutWithGoogle}
          className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded shadow"
        >
          ログアウト
        </button>
      ) : (
        <button
          onClick={signInWithGoogle}
          className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded shadow"
        >
          Googleログインして開始する
        </button>
      )}
    </>
  );
};

まずサインインボタンとログアウトボタンを作成します。

サインイン処理

signInWithPopupを使用し、引数には先ほどexportしたauthproviderを渡します。成功したら"/tasks"へ遷移させています。

ログアウト処理

authの中にsignOutメソッドが提供されているためそちらを使用します。

ログイン状態を確認

ログイン状態を提供してくれる便利なフックがあるためインストールします。

npm i react-firebase-hooks

useAuthStateをインポートします。

useAuthStateの引数にauthを渡しユーザー情報を受け取ります。未ログインの場合はnullになります。
ユーザー情報が存在したらログアウトボタンに、nullの場合はサインインボタンを表示するようにしています。

ログインしてみる

サインインボタンを押下します。

Googleログインのポップアップが出ました。

ログイン成功!

おまけ

APIKEYが無効エラーがでたが?【解決】

FirebaseError: Firebase: Error (auth/invalid-api-key).
APIKEYを環境変数においたら無効とか言われました!
envを確認しても値は合ってる。。。

これですがおそらく原因は「exportしたauthの機能をクライアント側で使っているため」です!
process.env.FIREBASE_APIKEYこの書き方はサーバー側でしか参照されないんですね〜

https://zenn.dev/kiwichan101kg/articles/fd6a94b5edc91a

クライアント側で使いたかったらNEXT_PUBLIC_をつけるか、Next.jsのenv機能を使用してクライアント側に値を流してあげる必要があります!

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  env: {
    FIREBASE_APIKEY: process.env.FIREBASE_APIKEY,
  },
};

export default nextConfig;

これでエラーが発生しなくなりました!

まとめ

ログイン機能は外部に任せるのが安心安全なので個人開発ではfirebaseのAuthenticationを利用しようと思います!

Discussion