← 返回 Skills 市场
guifav

Firebase Auth Setup

作者 Guilherme Favaron · GitHub ↗ · v0.1.2 · MIT-0
cross-platform ⚠ suspicious
759
总下载
0
收藏
0
当前安装
3
版本数
在 OpenClaw 中安装
/install firebase-auth-setup
功能描述
Configures Firebase Authentication — providers, security rules, custom claims, and React auth hooks
使用说明 (SKILL.md)

Firebase Auth Setup

You are a security-focused engineer responsible for configuring Firebase Authentication in Next.js App Router projects. You set up auth providers, create React hooks, configure middleware, and sync Firebase users with Supabase profiles.

Planning Protocol (MANDATORY — execute before ANY action)

Before creating or modifying any auth configuration, you MUST complete this planning phase:

  1. Understand the request. Determine: (a) which auth providers are needed, (b) whether this is initial setup or adding to an existing configuration, (c) any role-based access requirements (custom claims), (d) whether Firebase-Supabase sync is already configured.

  2. Survey the existing auth setup. Check: (a) src/lib/firebase/ for existing client and admin SDK initialization, (b) src/hooks/use-auth.ts for existing auth hooks, (c) src/middleware.ts for existing auth middleware, (d) src/app/api/auth/ for existing sync routes, (e) .env.example (NOT .env.local) to see which Firebase env vars are expected. Do NOT read .env.local or any file containing actual credential values.

  3. Build an execution plan. Write out: (a) which files need to be created vs modified, (b) the dependency order (SDK init first, then hooks, then components, then sync route), (c) which Firebase Console settings the user will need to configure manually.

  4. Identify risks. Flag: (a) changes to auth middleware that could lock out existing users, (b) sync route changes that could break the Firebase-Supabase user mapping, (c) missing env vars that will cause runtime errors. For each risk, define the mitigation.

  5. Execute step by step. Create or modify files in dependency order. After each file, verify it compiles. Test the auth flow end-to-end if possible.

  6. Summarize. Report what was configured, which files are new or modified, and the manual steps the user must complete in the Firebase Console (enable providers, add authorized domains, etc.).

Do NOT skip this protocol. Auth misconfiguration can lock users out or create security vulnerabilities.

Architecture Overview

This stack uses Firebase for authentication and Supabase for data storage. The flow is:

  1. User authenticates via Firebase (Google, Apple, email/password, etc.).
  2. Firebase issues a JWT (ID token).
  3. The Next.js middleware or Server Component verifies the token via Firebase Admin SDK.
  4. A corresponding Supabase profile is created/updated (synced via a trigger or API route).
  5. Supabase RLS policies use the Firebase UID stored in the profiles.id column.

Auth Hook

Create/update src/hooks/use-auth.ts:

"use client";

import { useEffect, useState, useCallback } from "react";
import {
  onAuthStateChanged,
  signInWithPopup,
  signInWithEmailAndPassword,
  createUserWithEmailAndPassword,
  signOut as firebaseSignOut,
  GoogleAuthProvider,
  OAuthProvider,
  type User,
} from "firebase/auth";
import { auth } from "@/lib/firebase/client";

interface AuthState {
  user: User | null;
  loading: boolean;
  error: string | null;
}

export function useAuth() {
  const [state, setState] = useState\x3CAuthState>({
    user: null,
    loading: true,
    error: null,
  });

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setState({ user, loading: false, error: null });
    });
    return unsubscribe;
  }, []);

  const signInWithGoogle = useCallback(async () => {
    try {
      setState((prev) => ({ ...prev, loading: true, error: null }));
      const provider = new GoogleAuthProvider();
      await signInWithPopup(auth, provider);
    } catch (error: any) {
      setState((prev) => ({ ...prev, loading: false, error: error.message }));
    }
  }, []);

  const signInWithApple = useCallback(async () => {
    try {
      setState((prev) => ({ ...prev, loading: true, error: null }));
      const provider = new OAuthProvider("apple.com");
      provider.addScope("email");
      provider.addScope("name");
      await signInWithPopup(auth, provider);
    } catch (error: any) {
      setState((prev) => ({ ...prev, loading: false, error: error.message }));
    }
  }, []);

  const signInWithEmail = useCallback(
    async (email: string, password: string) => {
      try {
        setState((prev) => ({ ...prev, loading: true, error: null }));
        await signInWithEmailAndPassword(auth, email, password);
      } catch (error: any) {
        setState((prev) => ({ ...prev, loading: false, error: error.message }));
      }
    },
    []
  );

  const signUpWithEmail = useCallback(
    async (email: string, password: string) => {
      try {
        setState((prev) => ({ ...prev, loading: true, error: null }));
        await createUserWithEmailAndPassword(auth, email, password);
      } catch (error: any) {
        setState((prev) => ({ ...prev, loading: false, error: error.message }));
      }
    },
    []
  );

  const signOut = useCallback(async () => {
    try {
      await firebaseSignOut(auth);
    } catch (error: any) {
      setState((prev) => ({ ...prev, error: error.message }));
    }
  }, []);

  return {
    ...state,
    signInWithGoogle,
    signInWithApple,
    signInWithEmail,
    signUpWithEmail,
    signOut,
  };
}

Auth Provider Component

Create src/components/shared/auth-provider.tsx:

"use client";

import { createContext, useContext } from "react";
import { useAuth } from "@/hooks/use-auth";
import type { User } from "firebase/auth";

interface AuthContextType {
  user: User | null;
  loading: boolean;
  error: string | null;
  signInWithGoogle: () => Promise\x3Cvoid>;
  signInWithApple: () => Promise\x3Cvoid>;
  signInWithEmail: (email: string, password: string) => Promise\x3Cvoid>;
  signUpWithEmail: (email: string, password: string) => Promise\x3Cvoid>;
  signOut: () => Promise\x3Cvoid>;
}

const AuthContext = createContext\x3CAuthContextType | undefined>(undefined);

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const auth = useAuth();
  return \x3CAuthContext.Provider value={auth}>{children}\x3C/AuthContext.Provider>;
}

export function useAuthContext() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuthContext must be used within an AuthProvider");
  }
  return context;
}

Server-Side Token Verification

Create/update src/lib/firebase/verify-token.ts:

import { adminAuth } from "@/lib/firebase/admin";

export async function verifyFirebaseToken(token: string) {
  try {
    const decodedToken = await adminAuth.verifyIdToken(token);
    return { uid: decodedToken.uid, email: decodedToken.email };
  } catch {
    return null;
  }
}

Firebase-Supabase User Sync

Create src/app/api/auth/sync/route.ts to sync Firebase users with Supabase profiles:

import { NextRequest, NextResponse } from "next/server";
import { adminAuth } from "@/lib/firebase/admin";
import { createClient } from "@supabase/supabase-js";

// Use service role for admin operations
const supabaseAdmin = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!
);

export async function POST(request: NextRequest) {
  const authHeader = request.headers.get("Authorization");
  if (!authHeader?.startsWith("Bearer ")) {
    return NextResponse.json({ error: "Missing token" }, { status: 401 });
  }

  try {
    const token = authHeader.split("Bearer ")[1];
    const decoded = await adminAuth.verifyIdToken(token);

    // Upsert profile in Supabase
    const { error } = await supabaseAdmin
      .from("profiles")
      .upsert(
        {
          id: decoded.uid,
          email: decoded.email || "",
          full_name: decoded.name || null,
          avatar_url: decoded.picture || null,
          updated_at: new Date().toISOString(),
        },
        { onConflict: "id" }
      );

    if (error) throw error;

    return NextResponse.json({ success: true });
  } catch (error: any) {
    return NextResponse.json(
      { error: error.message },
      { status: 401 }
    );
  }
}

Login Page Template

Create src/app/(auth)/login/page.tsx:

"use client";

import { useAuthContext } from "@/components/shared/auth-provider";
import { useRouter } from "next/navigation";
import { useEffect } from "react";

export default function LoginPage() {
  const { user, loading, error, signInWithGoogle, signInWithApple } =
    useAuthContext();
  const router = useRouter();

  useEffect(() => {
    if (user && !loading) {
      // Sync with Supabase on login
      user.getIdToken().then((token) => {
        fetch("/api/auth/sync", {
          method: "POST",
          headers: { Authorization: `Bearer ${token}` },
        }).then(() => router.push("/dashboard"));
      });
    }
  }, [user, loading, router]);

  if (loading) {
    return (
      \x3Cdiv className="flex min-h-screen items-center justify-center">
        \x3Cp className="text-muted-foreground">Loading...\x3C/p>
      \x3C/div>
    );
  }

  return (
    \x3Cdiv className="flex min-h-screen items-center justify-center px-4">
      \x3Cdiv className="w-full max-w-sm space-y-6">
        \x3Cdiv className="text-center">
          \x3Ch1 className="text-2xl font-bold">Sign In\x3C/h1>
          \x3Cp className="mt-2 text-sm text-gray-500">
            Choose your preferred sign-in method
          \x3C/p>
        \x3C/div>

        {error && (
          \x3Cp className="rounded-md bg-red-50 p-3 text-sm text-red-600">
            {error}
          \x3C/p>
        )}

        \x3Cdiv className="space-y-3">
          \x3Cbutton
            onClick={signInWithGoogle}
            className="flex w-full items-center justify-center gap-2 rounded-lg border px-4 py-3 text-sm font-medium hover:bg-gray-50 transition-colors"
          >
            Continue with Google
          \x3C/button>
          \x3Cbutton
            onClick={signInWithApple}
            className="flex w-full items-center justify-center gap-2 rounded-lg border bg-black text-white px-4 py-3 text-sm font-medium hover:bg-gray-900 transition-colors"
          >
            Continue with Apple
          \x3C/button>
        \x3C/div>
      \x3C/div>
    \x3C/div>
  );
}

Custom Claims

For role-based access (admin, editor, viewer):

// Set custom claims (run from a secure server context or admin script)
import { adminAuth } from "@/lib/firebase/admin";

export async function setUserRole(uid: string, role: "admin" | "editor" | "viewer") {
  await adminAuth.setCustomUserClaims(uid, { role });
}

// Verify role in API routes
export async function getUserRole(token: string): Promise\x3Cstring | null> {
  try {
    const decoded = await adminAuth.verifyIdToken(token);
    return (decoded.role as string) || null;
  } catch {
    return null;
  }
}

Adding a New Auth Provider

When the user asks to add a new provider:

  1. Update the useAuth hook with the new sign-in method.
  2. Add the provider button to the login page.
  3. Test the flow locally.
  4. Remind the user to enable the provider in the Firebase Console (Settings > Authentication > Sign-in method).
  5. Commit: feat: add \x3Cprovider> authentication.

Security Checklist

  • Firebase API keys are in .env.local (never committed).
  • Firebase Admin credentials use environment variables.
  • ID tokens are verified on the server for every protected route.
  • Custom claims are only set via server-side admin SDK.
  • The sync endpoint uses Firebase Admin to verify tokens.
  • CORS is properly configured for the auth domain.
  • Rate limiting is applied to auth endpoints (via Cloudflare Guard skill).
安全使用建议
This skill's code-free instructions look reasonable for configuring Firebase auth and a Firebase→Supabase sync, but there are important inconsistencies you should resolve before installing or running it: - Confirm required secrets: claw.json declares FIREBASE_PRIVATE_KEY and SUPABASE_SERVICE_ROLE_KEY (highly sensitive). Ask the author why these are required and whether they are mandatory for the skill to run or only needed for optional end-to-end tests. Prefer to provide such keys manually and only in a development environment. - Verify the manifest vs registry metadata: the top-level Requirements showed no required env vars or binaries, but claw.json does. That mismatch could be a packaging error or intentional—get clarification. - Inspect any created API routes before deploying: the SKILL.md will add server-side routes that operate with service credentials. Review those routes for authorization checks, rate limiting, and whether they leak tokens or accept unauthenticated requests. - Follow the Planning Protocol locally and run changes in a feature branch or staging environment. Back up existing auth-related files and test lockout scenarios (middleware changes) on a non-production environment. - If you need higher assurance, request the skill author to provide a minimal proof (diff or example files) showing how credentials are consumed (e.g., using process.env only in server-only code, not client bundles), and whether any remote endpoints are contacted besides Firebase and Supabase. If the author confirms claw.json is accurate and requires the listed creds, treat those as required for full functionality and only supply them in controlled, auditable environments (or create short-lived test credentials). If they cannot justify the sensitive envs or cannot explain the registry/manifest mismatch, do not install the skill.
功能分析
Type: OpenClaw Skill Name: firebase-auth-setup Version: 0.1.2 The skill provides standard templates and instructions for configuring Firebase Authentication and syncing user profiles with Supabase in Next.js projects. It includes a mandatory security-focused planning protocol in SKILL.md that explicitly forbids the agent from reading sensitive credential files like .env.local. The implementation of the sync API route (src/app/api/auth/sync/route.ts) and auth hooks follows common development patterns without any signs of malicious intent or data exfiltration.
能力评估
Purpose & Capability
The SKILL.md describes Firebase auth setup, provider hooks, middleware, and a Firebase→Supabase sync — which legitimately may require Firebase admin credentials and a Supabase service role key. However, the registry metadata provided to you at the top lists no required env vars or binaries, while claw.json (bundled with the skill) declares many required env vars (including FIREBASE_PRIVATE_KEY and SUPABASE_SERVICE_ROLE_KEY) and required binaries (node, npx). This mismatch is an incoherence: either the skill genuinely needs these sensitive creds/binaries or the manifest is stale/incorrect.
Instruction Scope
The SKILL.md itself is conservative: it mandates a planning protocol, tells the agent to inspect project files (src/lib/firebase, hooks, middleware, .env.example) and explicitly instructs not to read .env.local or any file containing actual credential values. It also asks to 'test end-to-end if possible', which is vague and could imply needing live credentials. Overall the runtime instructions stay within the auth setup scope but leave room for ambiguous actions when credentials are required.
Install Mechanism
This is an instruction-only skill with no install spec and no code files to execute, which is low-risk from an installer perspective. There is no remote download or arbitrary code execution specified in the manifest.
Credentials
The claw.json lists multiple highly sensitive environment variables (FIREBASE_PRIVATE_KEY, FIREBASE_CLIENT_EMAIL, SUPABASE_SERVICE_ROLE_KEY, etc.). Those are proportionate to implementing server-side Firebase Admin verification and Supabase service operations, but the earlier provided 'Requirements' block claimed none. Requesting multiple production-level credentials without a clear, consistent declaration is concerning. Also 'NEXT_PUBLIC_*' vars are public, but private keys should be handled carefully — the skill's instructions try to avoid reading actual credential files, but the manifest suggests these secrets may be needed for testing or verification.
Persistence & Privilege
The skill is not always-enabled and is user-invocable, which is normal. claw.json includes a filesystem permission (expected for a skill that will create/modify project files). There is no evidence the skill attempts to persist beyond its own files or modify other skills or global agent settings.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install firebase-auth-setup
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /firebase-auth-setup 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v0.1.2
firebase-auth-setup 0.1.2 - Added a CHANGELOG.md file for improved tracking of changes. - Updated claw.json configuration.
v0.1.1
- Planning protocol updated: You must only use `.env.example` (not `.env.local`) when checking for expected Firebase environment variables, to prevent accidental reading of real credentials. - Documentation clarified in the Planning Protocol step 2 for improved security and review procedures. - No logic or API changes; only the setup/checklist process and documentation were updated.
v0.1.0
Version 0.1.0 - Initial release of Firebase Auth Setup skill. - Provides a strict planning protocol to ensure secure and reliable setup of Firebase Auth and Firebase-Supabase sync. - Includes ready-to-use React hooks and AuthProvider component for client authentication. - Delivers examples for Next.js server-side token verification. - Supplies an API route for syncing Firebase users with Supabase profiles. - Focuses on security, mitigation of auth risks, and detailed manual steps for correct provider/config setup.
元数据
Slug firebase-auth-setup
版本 0.1.2
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 3
常见问题

Firebase Auth Setup 是什么?

Configures Firebase Authentication — providers, security rules, custom claims, and React auth hooks. 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 759 次。

如何安装 Firebase Auth Setup?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install firebase-auth-setup」即可一键安装,无需额外配置。

Firebase Auth Setup 是免费的吗?

是的,Firebase Auth Setup 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

Firebase Auth Setup 支持哪些平台?

Firebase Auth Setup 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Firebase Auth Setup?

由 Guilherme Favaron(@guifav)开发并维护,当前版本 v0.1.2。

💬 留言讨论