Posted in

Supabase 实时:广播和在线状态授权_AI阅读总结 — 包阅AI

包阅导读总结

1.

关键词:Supabase Realtime、Broadcast、Presence、Authorization、Row Level Security

2.

总结:本文介绍了 Supabase Realtime 的 Broadcast 和 Presence 的授权功能发布,通过行级安全策略实现,创建并管理消息表,可编写 RLS 策略控制访问,介绍了配置、检查方式及相关示例,目前处于公开测试阶段,期待反馈。

3.

主要内容:

– Supabase Realtime 包括 Broadcast、Presence 和 Postgres Changes 三个用于构建实时应用的扩展

– Broadcast 用于用户间发送短暂低延迟消息

– Presence 展示用户在线状态并共享状态

– 此次发布为 Broadcast 和 Presence 引入授权,使用行级安全策略

– Realtime 在数据库实时模式创建并管理消息表

– 可编写 RLS 策略,决定客户端对频道的访问权限

– 连接实时频道时可设置授权

– 提供了简单和复杂的策略示例

– 如允许认证用户完全访问 Broadcast 和 Presence

– 可通过新数据库函数和扩展列控制

– 介绍新配置参数 private 用于检查频道授权

– 未授权用户订阅会报错

– 授权用户可正常连接

– 解释了 Realtime 授权的实现方式和策略缓存机制

– 基于频道订阅检查,会有小延迟但会缓存

– 考虑用户连接、令牌刷新和过期等情况

– 目前此授权方法仅支持 Broadcast 和 Presence,Postgres Changes 遵循已有授权方案,该功能处于公开测试阶段,期待反馈

思维导图:

文章地址:https://supabase.com/blog/supabase-realtime-broadcast-and-presence-authorization

文章来源:supabase.com

作者:Supabase Blog

发布时间:2024/8/13 0:00

语言:英文

总字数:1284字

预计阅读时间:6分钟

评分:82分

标签:实时,授权,行级安全,广播,在线状态


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

Today we’re releasing Authorization for Realtime’s Broadcast and Presence.

For context, Supabase includes three useful extensions for building real-time applications.

  1. Broadcast: Send ephemeral, low-latency messages between users.
  2. Presence: Show when users are online and share state between users.
  3. Postgres Changes: Listen to Postgres database changes.

This release introduces authorization for Broadcast and Presence using Row Level Security policies:

To facilitate this, Realtime creates and manages a messages table in your Database’s realtime schema:

You can then write RLS Policies for this table and Realtime will then allow or deny clients’ access to your Broadcast and Presence Channels:

  • SELECT Policies – Allow/Deny receiving messages
  • INSERT Policies – Allow/Deny sending messages

When you want to connect to a Realtime Channel, you can do the following:

_15

import { createClient } from '@supabase/supabase-js'

_15

// Prepare client with authenticated user

_15

const client = createClient('<url>', '<anon_key>')

_15

client.realtime.setAuth(token)

_15

// Prepare the realtime channel

_15

const channel = client.channel('topic')

_15

.subscribe((status: string, err: any) => {

_15

if (status === 'SUBSCRIBED') {

_15

console.log('Connected')

Without Authorization, any authenticated client can subscribe to any public Channel, to send and receive any messages.

You can convert this into an authorized Channel (one that verifies RLS policies) in two steps:

  1. Create RLS Policies
  2. Enabling Authorization on Channels

We’ll keep it simple with this example. Let’s allow authenticated users to:

  • Broadcast: send and receive messages (full access)
  • Presence: sync, track, and untrack (full access)

_13

create policy "authenticated user listen to all"

_13

on "realtime"."messages"

_13

create policy "authenticated user write to all"

_13

on "realtime"."messages"

We also have a new database function called realtime.topic(). You can use this to access the name of the Channel inside your Policies:

_10

create policy "authenticated users can only read from 'locked' topic"

_10

on "realtime"."messages"

_10

for select -- read only

_10

realtime.topic() = 'locked' -- access the topic name

You can use the extension column in the messages table to allow/deny specify the Realtime extension:

_10

create policy "read access to broadcast and presence"

_10

on "realtime"."messages"

_10

realtime.messages.extension in ('broadcast', 'presence') -- specify the topic name

Reference our Github Discussion for more complex use cases.

We’ve introduced a new configuration parameter private to signal to Realtime servers that you want to check authorization on the channel.

If you try to subscribe with an unauthorized user you will get a new error message informing the user that they do not have permission to access the topic.

_13

.channel('locked', { config: { private: true } })

_13

.subscribe((status: string, err: any) => {

_13

if (status === 'SUBSCRIBED') {

_13

console.log('Connected!')

_13

console.error(err.message)

_13

// Outputs the following code:

_13

// "You do not have permissions to read from this Topic"

But if you connect with an authorized user you will be able to listen to all messages from the “locked” topic

_15

// With an authenticated user

_15

supabase.realtime.setAuth(token)

_15

.channel('locked', { config: { private: true } })

_15

.subscribe((status: string, err: any) => {

_15

if (status === 'SUBSCRIBED') {

_15

console.log('Connected!')

_15

console.error(err.message)

_15

// Outputs the following code:

You can find a more complex example in the Next.js Authorization Demo where we are using this feature to build chat rooms with restricted access or you could check the Flutter Figma Clone to see how you can secure realtime communication between users.

We decided on an approach that keeps your database and RLS policies at the heart of this new authorization strategy.

To achieve Realtime authorization, we looked into our current solutions, namely how Storage handles Access Control. Due to the nature of Realtime, our primitives are different as we have no assets stored in the database. So how did we achieve it?

On Channel subscription you are able to inform Realtime to use a private Channel and we will do the required checks.

The checks are done by running SELECT and INSERT queries on the new realtime.messages table which are then rolled backed so nothing is persisted. Then, based on the query result, we can determine the policies the user has for a given extension.

As a result, in the server, we create a map of policies per connected socket so we can keep them in memory associated with the user’s connection.

_10

broadcast: %BroadcastPolicies{read: false, write: false},

_10

presence: %PresencePolicies{read: false, write: false}

One user, one context, one connection#

Now that we have set up everything on the database side, let’s understand how it works and how we can verify authorization via RLS policies.

Realtime uses the private flag client’s define when creating channel, takes the headers used to upgrade to the WebSocket connection, claims from your verified JSON Web Token (JWT), loads them into a Postgres transaction using set_config, verifies them by querying the realtime.messages table, and stores the output as a group of policies within the context of the user’s channel on the server.

Realtime checks RLS policies against your database on Channel subscription, so expect a small latency increase initially, but will be cached on the server so all messages will pass from client to server to clients with minimal latency.

Latency between geographically close users is very important for a product like Realtime. To deliver messages as fast as possible between users on our global network, we cache the policies.

We can maintain high throughput and low latency on a Realtime Channel with Broadcast and Presence authorization because:

  • the policy is only generated when a user connects to a Channel
  • the policy cached in memory is close to your users
  • the policy is cached for the duration of the connection, until the JWT expires, or when the user sends a new refresh token

If a user does not have access to a given Channel they won’t be able to connect at all and their connections will be rejected.

Realtime will check RLS policies against your database whenever the user connects or there’s a new refresh token to make sure that it continues to be authorized despite any changes to its claims. Be aware of your token expiration time to ensure users policies are checked regularly.

Postgres Changes Support#

This method for Realtime Authorization currently only supports Broadcast and Presence. Postgres Changes already adheres to RLS policies on the tables you’re listening to so you can continue using that authorization scheme for getting changes from your database.

Broadcast and Presence Authorization is available in Public Beta. We are looking for feedback so please do share it in the GitHub discussion.

We’re excited to make Realtime more secure, performant, and stable.

We’ll take your feedback, expand this approach, and continue to improve the developer experience as you implement Realtime Authorization for your use cases.