🔐

Next.js Firebase 匿名認証を行う

2024/12/15に公開

🤔やってみたいこと

JavaScript を使用して Firebase 匿名認証を行う

Firebase Authentication で一時的な匿名アカウントを作成して使用することで、Firebase で認証できます。一時的な匿名アカウントを使用すると、アプリに登録していないユーザーが、セキュリティ ルールで保護されているデータを使用できるようになります。匿名ユーザーがアプリに登録する場合は、ログイン認証情報を匿名アカウントにリンクすると、それ以後のセッションでも引き続き、保護されているデータを使用できます。

JavaScript を使用して Firebase 匿名認証を行う

公式に、Next.jsでやる方法は書いていない😇
middleware.tsに認証の処理を記載する。
https://nextjs.org/docs/app/building-your-application/routing/middleware

作ったデモ
認証が通っていない場合は、/dashboardへ遷移しない。認証が通っていればリダイレクトして、移動する。
https://youtu.be/Es81Nr68Duk

🚀やってみたこと

bunでプロジェクトを作成する。

bun create next-app

firebaseのライブラリを追加。

bun add firebase

Firebaseのコンソールから、API KEYをコピーして、firebase.tsに貼り付ける。

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
// 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
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "*********************",
  authDomain: "*********************",
  projectId: "*********************",
  messagingSenderId: "*********************",
  appId: "*********************",
  measurementId: "*********************",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

export const auth = getAuth(app);

middleware.tsを作成する。認証が通っているかいないかで遷移できないようにするには、こちらのファイルで設定をする。

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { auth } from './firebase'  // 既存のfirebase.tsから

export async function middleware(request: NextRequest) {
  try {
    const token = request.cookies.get('firebase-token')?.value

    if (!token) {
      return NextResponse.redirect(new URL('/auth/signin', request.url))
    }

    return NextResponse.next()
  } catch (error) {
    return NextResponse.redirect(new URL('/auth/signin', request.url))
  }
}

export const config = {
  matcher: [
    '/dashboard/:path*',
    '/profile/:path*'
  ]
}

UIを作成する。構成はこのようになっております。

app/auth/signin/page.tsxを作成する。ログインの実験をするときは、auth/signinのパスを指定してこちらのページまで行ってください。

// app/auth/signin/page.tsx
'use client'

import { auth } from '@/firebase'
import { signInAnonymously } from 'firebase/auth'

export default function SignIn() {
    const handleAnonymousSignIn = async () => {
        try {
            const userCredential = await signInAnonymously(auth)
            const token = await userCredential.user.getIdToken()

            // トークンをクッキーに保存
            document.cookie = `firebase-token=${token}; path=/`

            // ダッシュボードなどにリダイレクト
            window.location.href = '/dashboard'
        } catch (error) {
            console.error('匿名認証エラー:', error)
        }
    }

    return (
        <button onClick={handleAnonymousSignIn}>
            匿名でログイン
        </button>
    )
}

dashboard/page.tsxを作成する。こちらがログイン後のページ。SignOutボタンも必要と思い追加した。コンポーネントにして切り分けた。

// components/SignOutButton.tsx
'use client'

import { useState } from 'react'
import { auth } from "@/firebase"

export default function SignOutButton() {
    const [isLoading, setIsLoading] = useState(false)

    return (
        <button
            type="button"
            className="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 disabled:opacity-50"
            disabled={isLoading}
            onClick={async () => {
                try {
                    setIsLoading(true)
                    await auth.signOut()
                    document.cookie = "firebase-token=; path=/"
                    window.location.href = "/"
                } catch (error) {
                    console.error("Logout error:", error)
                } finally {
                    setIsLoading(false)
                }
            }}
        >
            {isLoading ? 'Signing out...' : 'Sign Out'}
        </button>
    )
}

ボタンしかないですが、認証機能を使う練習には十分かなと。

import SignOutButton from "./SignOutButton";


export default function Dashboard() {
    return (
        <div>
            <h1>Home</h1>
            <SignOutButton />
        </div>
    );
}

app/page.tsxはテキストを表示するだけのに変更。このページが最初に表示されて、パスを指定すると、auth/signinへ遷移します。

import React from 'react'

const Home = () => {
  return (
    <div>Home</div>
  )
}

export default Home

🙂最後に

今回は、FirebaseAuthenticationでログイン機能を実装してみました。すごくシンプルですが、情報がないと作るのは難しい😅

色々テンプレートを作っておけば個人開発やもしかしたら、仕事で役に立つかもしれない?

Discussion