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

使用自定义JWT时Supabase实时连接失败问题求助

自托管Supabase结合Auth0认证时Realtime订阅的JWT认证问题

问题描述

我使用自托管Supabase,采用Auth0进行认证而非Supabase默认认证方案。我用Supabase密钥对包含用户ID的负载进行签名,并将生成的JWT放在请求头Authorization中,普通数据库查询(已开启RLS策略)可正常执行,但创建Realtime订阅时,WebSocket连接抛出认证错误;若不携带自定义JWT则连接正常,但我需要将自定义JWT的payload传入Realtime订阅,以便在RLS策略中使用。

当前实现代码:

const payload = {
    userId: user.email,
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
}
const accessToken = jwt.sign(payload, SUPABASE_SECRET_KEY)

const options = {}

if (accessToken) {
  options.global = {
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  }
}
const supabase = createClient(supabaseUrl, supabaseAnonKey, options)
supabase.channel('custom-update-channel')
.on(
  'postgres_changes',
  { event: 'UPDATE', schema: 'public', table: 'user_notifications' },
  (payload) => { 
      console.log('Change received!', payload)
  }
)
.subscribe()

解决方案

1. 补全自定义JWT的必要字段

Realtime服务对JWT有额外字段要求,除了exp(过期时间),必须包含iat(签发时间)字段,同时建议添加sub字段(Realtime内部依赖此字段做身份关联)。修改JWT生成代码:

const payload = {
    userId: user.email,
    sub: user.email, // 与userId保持一致即可
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
    iat: Math.floor(Date.now() / 1000) // 新增签发时间字段
}
const accessToken = jwt.sign(payload, SUPABASE_SECRET_KEY)

2. 配置自托管Realtime的JWT验证规则

自托管Supabase的Realtime默认会校验JWT的iss(签发者)字段,需要在Realtime服务配置中适配自定义JWT:

  • 打开自托管环境的docker-compose.yml文件,找到realtime服务的environment配置段
  • 添加REALTIME_JWT_ISS=your-auth0-domain(替换为你的Auth0域名,比如https://your-auth0-domain.auth0.com/),如果是测试环境可临时设置REALTIME_JWT_ALLOW_ANY=true(不推荐生产环境使用)
  • 重启Realtime服务使配置生效

3. 显式为Realtime连接传递JWT

Supabase JS客户端的全局header设置不会自动同步到WebSocket连接,需要在订阅时显式传递认证信息:

supabase.channel('custom-update-channel')
.on(
  'postgres_changes',
  { event: 'UPDATE', schema: 'public', table: 'user_notifications' },
  (payload) => { 
      console.log('Change received!', payload)
  }
)
.subscribe({
  auth: {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  }
})

4. 确保RLS策略兼容Realtime角色

Realtime服务使用realtime角色访问数据库,需要在RLS策略中包含该角色:

CREATE POLICY "User can access their own notifications" ON public.user_notifications
FOR ALL TO authenticated, realtime USING (
  (current_setting('request.jwt.claims', true)::json->>'userId') = email
)
WITH CHECK (
  (current_setting('request.jwt.claims', true)::json->>'userId') = email
);

内容的提问来源于stack exchange,提问作者Goutham Raj R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:01:10