You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Supabase中实现认证而不混用Server Actions与Client Actions?

问题:Supabase + Next.js 混和认证导致状态追踪失效

我用Supabase和NextJS实现认证功能,大部分操作(登录、注册等)采用服务端实现,但登出操作按照Supabase文档建议用客户端实现。这种服务端与客户端操作的混用,导致无法可靠追踪认证状态变化——因为每种操作仅会向客户端或服务端触发事件。我尝试实现一个根据用户登录状态切换登录/登出按钮的Header,但目前完全无法正常工作。

客户端登出代码(src/app/auth/sign-out/actions.ts)

'use client';
// src/app/auth/sign-out/actions.ts
import { createClient } from '@/lib/supabase/client';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';

export async function signout() {
    const supabase = await createClient();
    console.log("its working")

    const { error } = await supabase.auth.signOut({ scope: "local" });
    if (error) {
        return { success: false, error: error.message };
    }

    return { success: true };
}

服务端认证操作代码(src/lib/auth-actions.ts)

// src/lib/auth-actions.ts
'use server'

import { revalidatePath } from 'next/cache'
import { redirect } from 'next/navigation'

import { createClient } from '@/lib/supabase/server'

export async function login(formData: FormData) {
  const supabase = await createClient()
  const data = {
    email: formData.get('email') as string,
    password: formData.get('password') as string,
  }
  const { error } = await supabase.auth.signInWithPassword(data)
  if (error) {
    return { success: false, error: error.message }
  }
  revalidatePath('/', 'layout')
  redirect('/')
  return { success: true, error: "" }
}

export async function signup(formData: FormData) {
  const supabase = await createClient()
  const data = {
    email: formData.get('email') as string,
    password: formData.get('password') as string,
    options: {
        data: {
            fname: formData.get('fname') as string,
            lname: formData.get('lname') as string,
        }
    }
  }
  const { error } = await supabase.auth.signUp(data)
  console.log(error)
  if (error) {
    return { success: false, error: error.message }
  }
  revalidatePath('/', 'layout')
  return { success: true, error: null }
}


export async function loginWithGoogle() {
    const supabase = await createClient();

    const { data, error } = await supabase.auth.signInWithOAuth({
        provider: 'google',
        options: {
            queryParams: {
                access_type: "offline",
                prompt: "consent",
            }
        }
    });

    if (data.url) {
        redirect(data.url) // use the redirect API for your server framework
    }

    redirect("/")
    return { success: !error, error: error ? error.message : null };
}

export async function sendPasswordResetEmail(email: string) {
  const supabase = await createClient();
  const { data, error } = await supabase.auth.resetPasswordForEmail(email);

  if (error) {
    return { success: false, error: error.message };
  }

  return { success: true, error: null };
}

export async function updatePassword(newPassword: string) {
  const supabase = await createClient();
  const { error } = await supabase.auth.updateUser({ password: newPassword });

  if (error) {
    return { success: false, error: error.message };
  }

  return { success: true, error: null };
}
// src/components/Navbar.tsx
'use server';

import AuthBtn from "./AuthBtn";
import { createClient } from "@/lib/supabase/server";

export default async function Navbar() {
  const supabase = await createClient();
  const {
    data: { user },
  } = await supabase.auth.getUser();

  return (
    <header className="bg-teal-500 w-full relative z-50 shadow-md">
      <nav className="container mx-auto px-6 py-4 flex justify-between items-center">
        {/* Title */}
        <h1 className="text-white font-bold text-2xl">Newsly</h1>
        <AuthBtn isLoggedIn={!!user} />
      </nav>
    </header>
  );
}

已尝试的解决方案

  • 使用Context和AuthProvider组件统一管理认证状态
  • 在layout.tsx中使用服务端Supabase实例,Navbar.tsx中使用客户端实例
    以上方法均未解决问题。

内容的提问来源于stack exchange,提问作者frzzled

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 10:44:54