在Astro中使用Supabase的Magic Link实现用户登录失败
问题描述
点击邮件中的链接后跳转到首页,URL中可见access token,但调用getUser函数时,console.log(user)输出为null。
相关代码
src/auth.ts
import { createClient } from '@supabase/supabase-js'; import cookie from 'cookie'; export const supabase = createClient( import.meta.env.PUBLIC_SUPABASE_URL, import.meta.env.PUBLIC_SUPABASE_ANON_KEY ); export async function getUser(req: Request) { const c = cookie.parse(req.headers.get('cookie') ?? ''); if (!c.sbat) { return null; } console.log(c.sbat); const { data: { user }, } = await supabase.auth.getUser(c.sbat); if (!user || user.role !== 'authenticated') { return null; } console.log(user); return user; } export async function isLoggedIn(req: Request) { return (await getUser(req)) != null; }
src/pages/api/login.astro
--- import {supabase} from "../../auth" const body = await Astro.request.json(); Astro.response.headers.set('Set-Cookie', `sbat=${body.access_token}; Path=/;`); ---
问题分析与解决方案
1. 前端未处理URL中的token,导致cookie未设置
邮件跳转后URL里的access token需要前端主动提取并传给/api/login接口,才能将token写入cookie。如果前端没有做这一步,getUser函数中c.sbat会为空,直接返回null。
解决步骤:
在首页的 Astro 组件中添加URL参数处理逻辑,提取access token并调用登录接口:
--- // src/pages/index.astro if (Astro.url.searchParams.get('access_token')) { const accessToken = Astro.url.searchParams.get('access_token'); await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ access_token: accessToken }) }); // 重定向去掉URL中的token,避免重复处理 return Astro.redirect(Astro.url.origin); } ---
2. Access Token无效或不匹配
可能URL中的token是refresh token而非access token,或者token已过期、与Supabase项目配置不匹配。
验证方式:
在getUser函数中添加错误捕获,打印详细错误信息:
export async function getUser(req: Request) { const c = cookie.parse(req.headers.get('cookie') ?? ''); if (!c.sbat) { return null; } console.log(c.sbat); try { const { data: { user }, error } = await supabase.auth.getUser(c.sbat); if (error) { console.error('获取用户信息失败:', error); return null; } if (!user || user.role !== 'authenticated') { return null; } console.log(user); return user; } catch (err) { console.error('请求异常:', err); return null; } }
3. Cookie设置属性缺失
当前Set-Cookie仅设置了Path=/,缺少HttpOnly、SameSite等关键属性,可能导致cookie无法被后端正确读取(尤其是跨域或生产环境)。
优化Cookie设置:
修改/api/login.astro中的cookie配置:
--- import {supabase} from "../../auth" const body = await Astro.request.json(); const isProduction = import.meta.env.PROD; const cookieOptions = [ `sbat=${body.access_token}`, 'Path=/', 'HttpOnly', 'SameSite=Lax', isProduction ? 'Secure' : '' ].filter(Boolean).join('; '); Astro.response.headers.set('Set-Cookie', cookieOptions); ---
4. Supabase环境变量配置错误
检查PUBLIC_SUPABASE_URL和PUBLIC_SUPABASE_ANON_KEY是否与Supabase项目控制台中的信息完全一致,环境变量未正确加载会导致客户端初始化失败,无法验证token。
内容的提问来源于stack exchange,提问作者hey
相关产品推荐
相关产品推荐

