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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 08:28:38