Vercel Serverless Node.js API(非Next.js)无法通过Supabase认证用户
问题分析与解决方案
核心原因
这不是bug,是你遗漏了传递用户认证令牌的关键步骤:
- 用
createClient(supabaseUrl, supabaseKey)创建的是服务端密钥客户端,但auth.getUser()需要用户的JWT令牌来识别身份,没有这个令牌时,Supabase无法验证用户,就会返回"invalid claim: subject missing"错误。 - Next.js的
createServerSupabaseClient会自动从请求cookie中提取用户认证令牌并注入客户端,但普通Vercel无服务器函数不会自动处理这件事。 - 你提到浏览器JWT存在本地存储但请求API未携带cookie,这也是核心问题——服务端认证场景下,Supabase默认通过cookie传递令牌,请求不带cookie的话,服务端根本拿不到用户的JWT。
解决步骤
1. 前端请求携带认证cookie
前端调用Vercel函数时,必须配置credentials: 'include',让浏览器自动携带Supabase的认证cookie:
// 前端请求示例 fetch('/api/your-vercel-function', { method: 'GET', credentials: 'include' // 关键:携带cookie });
2. 服务端手动提取并注入JWT
在Vercel无服务器函数中,从请求cookie里提取access_token,创建客户端时传入该令牌:
import { createClient } from '@supabase/supabase-js'; export default async function handler(req) { // 从请求cookie中解析access_token const accessToken = req.headers.cookie?.split(';').find(c => c.trim().startsWith('sb-access-token='))?.split('=')[1]; if (!accessToken) { return new Response(JSON.stringify({ error: '未提供认证令牌' }), { status: 401 }); } // 创建带用户令牌的Supabase客户端 const supabaseClient = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY, { global: { headers: { Authorization: `Bearer ${accessToken}` } } }); try { const { data: { user }, error } = await supabaseClient.auth.getUser(); if (error) throw error; return new Response(JSON.stringify({ user }), { status: 200 }); } catch (error) { return new Response(JSON.stringify({ error: error.message }), { status: 500 }); } }
3. 额外配置检查
- 确保Supabase控制台的「Authentication → URL Configuration」中,已添加Vercel函数的域名到站点URL列表,否则浏览器会因跨域策略不发送cookie。
- 前端Supabase客户端初始化时,需设置
auth: { persistSession: true },确保JWT存储在cookie中(默认存在localStorage,不适合服务端认证场景)。
内容的提问来源于stack exchange,提问作者sw1337
相关产品推荐
相关产品推荐

