如何为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钩子,在服务端根据登录上下文自动添加平台标识:
- 创建自定义钩子函数:
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; $$;
- 注册钩子到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
相关产品推荐
相关产品推荐

