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

Next.js中用Supabase和SSR实现OAuth遇问题求助

Next.js + Supabase SSR OAuth认证流程中断问题解决

我在Next.js项目中使用Supabase结合@supabase/ssr集成OAuth认证,MagicLink和邮箱认证功能正常,但Google等社交提供商登录时流程意外中断。


现有实现代码

邮箱登录函数

async function signInWithEmail(formData: FormData) {
    "use server"

    const origin = headers().get("origin")
    const email = formData.get("email") as string
    const cookieStore = cookies()
    const supabase = createClient(cookieStore)

    const { error } = await supabase.auth.signInWithOtp({
      email: email,
      options: {
        emailRedirectTo: `${origin}/auth/callback`,
      },
    })

    if (error) {
      console.error(error)
      return redirect("/login?message=Could not authenticate user")
    }

    redirect("/login?message=Check your email inbox to continue signing in")
  }

认证回调代码

import { createClient } from "@/lib/supabase/server"
import { NextResponse } from "next/server"
import { cookies } from "next/headers"

export async function GET(request: Request) {
  const requestUrl = new URL(request.url)
  const code = requestUrl.searchParams.get("code")

  if (code) {
    const cookieStore = cookies()
    const supabase = createClient(cookieStore)
    await supabase.auth.exchangeCodeForSession(code)
  }

  return NextResponse.redirect(requestUrl.origin)
}

Supabase客户端初始化代码(lib/supabase/server.ts)

import { createServerClient, type CookieOptions } from "@supabase/ssr"
import { cookies } from "next/headers"

export const createClient = (cookieStore: ReturnType<typeof cookies>) => {
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        get(name: string) {
          return cookieStore.get(name)?.value
        },
        set(name: string, value: string, options: CookieOptions) {
          try {
            cookieStore.set({ name, value, ...options })
          } catch (error) {
            console.error(error)
          }
        },
        remove(name: string, options: CookieOptions) {
          try {
            cookieStore.set({ name, value: "", ...options })
          } catch (error) {
            console.error(error)
          }
        },
      },
    }
  )
}

存在问题的OAuth登录函数

async function signInWithSocialProvider(provider: any) {
    "use server"

    const origin = headers().get("origin")
    const cookieStore = cookies()
    const supabase = createClient(cookieStore)

    const { error } = await supabase.auth.signInWithOAuth({
      provider: provider,
      options: {
        redirectTo: `${origin}/auth/callback`,
      },
    })

    if (error) {
      console.error(error)
      return redirect("/login?message=Could not authenticate user")
    }
  }

问题详情

  • 核心疑问:
    1. Supabase与SSR的OAuth配置中是否存在遗漏?
    2. 该问题是否由Supabase或Next.js配置错误导致?
  • 预期行为:选择Google等社交提供商后,跳转至提供商登录页,完成认证后返回应用并建立会话。
  • 实际行为:OAuth初始请求后流程停滞,能生成sb-xxx-auth-token-code-verifier cookie,但未跳转至Google登录页,认证未完成。
  • 相关日志:生成了名为sb-mlirbfytwbmtpcchmvlr-auth-token-code-verifier的cookie,值为d8d738ef35947d057b013bb19adaee03e44d74003c47ea27b8426b59df264ece2a9f98f78fbdfc5d3e562f021bdf0e0460b633246e889b6c

解决方案

问题出在OAuth登录函数中未处理signInWithOAuth返回的跳转URL。修改后的完整函数如下:

async function signInWithSocialProvider(provider: any) {
    "use server"

    const origin = headers().get("origin")
    const cookieStore = cookies()
    const supabase = createClient(cookieStore)

    const { data, error } = await supabase.auth.signInWithOAuth({
      provider: provider,
      options: {
        redirectTo: `${origin}/auth/callback`,
      },
    })

    if (error) {
      console.error(error)
      return redirect("/login?message=Could not authenticate user")
    }

    redirect(data.url)
  }

关键修改点

  1. 从supabase.auth.signInWithOAuth的返回值中解构出data对象
  2. 在函数末尾添加redirect(data.url),触发跳转到社交提供商的登录页面

内容的提问来源于stack exchange,提问作者Mathias Riis Sorensen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:18:10