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

如何为Supabase跨平台登录的同一用户动态添加JWT元数据

解决方案:动态添加JWT元数据实现基于登录平台的RLS策略

核心问题分析

你之前的写法把平台标识放到了app_metadata里,但app_metadata是用户的持久化属性,仅在新用户创建时会写入数据库,已存在用户登录时不会更新该字段,这就导致无法动态切换JWT中的平台标识。要实现动态控制,需要避免修改持久化的用户数据,而是直接在JWT中注入动态字段。


方法1:前端登录时直接传递动态字段(简单快速)

不需要修改数据库,直接在signInWithOtp的options.data中传入自定义字段,这些字段会被自动添加到JWT的user_metadata中,无论用户是新创建还是已存在,且不会修改auth.users表中的数据:

const { data: OTPData, error: OTPError } = await supabaseClient.auth.signInWithOtp({
  phone: `91${phoneNo}`,
  options: {
    shouldCreateUser: true,
    channel: "whatsapp",
    data: {
      login_platform: "admin" // 直接传递自定义平台标识,不要嵌套app_metadata
    },
  },
});

对应的RLS策略示例

在目标数据表上创建策略,通过JWT中的user_metadata判断平台:

-- 管理端用户可访问所有数据
CREATE POLICY "Admin full access" ON public.your_table
FOR SELECT USING (auth.jwt()->'user_metadata'->>'login_platform' = 'admin');

-- 移动端用户仅可访问自己的数据
CREATE POLICY "Mobile user own data" ON public.your_table
FOR SELECT USING (auth.uid() = user_id AND auth.jwt()->'user_metadata'->>'login_platform' = 'mobile');

方法2:用Postgres钩子自动注入平台标识(更安全)

如果不想依赖前端传递参数(避免篡改),可以用Supabase Auth的自定义JWT钩子,在服务端根据登录上下文自动添加平台标识:

  1. 创建自定义钩子函数:
CREATE OR REPLACE FUNCTION public.custom_jwt_login_hook(event jsonb)
RETURNS jsonb
LANGUAGE plpgsql
AS $$
BEGIN
  -- 可根据登录渠道、客户端信息等动态判断平台
  -- 示例:通过登录channel判断,whatsapp对应管理端,sms对应移动端
  IF event->>'channel' = 'whatsapp' THEN
    RETURN event || jsonb_build_object('login_platform', 'admin');
  ELSE
    RETURN event || jsonb_build_object('login_platform', 'mobile');
  END IF;
END;
$$;
  1. 注册钩子到Supabase Auth:
ALTER SYSTEM SET supabase.auth.jwt_hook = 'public.custom_jwt_login_hook';
SELECT pg_reload_conf();

对应的RLS策略示例

直接使用JWT根级的login_platform字段(因为钩子直接添加到JWT根节点):

CREATE POLICY "Admin full access" ON public.your_table
FOR SELECT USING (auth.jwt()->>'login_platform' = 'admin');

CREATE POLICY "Mobile user own data" ON public.your_table
FOR SELECT USING (auth.uid() = user_id AND auth.jwt()->>'login_platform' = 'mobile');

关键注意事项

  • 不要用app_metadata存储动态变化的登录平台:app_metadata是持久化的用户属性,适合存储角色、权限等级这类不常变的信息。
  • 动态字段仅存在于JWT生命周期内:用户每次登录都会重新生成JWT,所以每次登录都可以注入最新的平台标识,完美适配RLS的动态权限控制需求。

内容的提问来源于stack exchange,提问作者Mohammed Yasin Mulla

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:51:02