在任何系统中,数据安全、访问控制等问题都至关重要,本篇我们介绍一下Supabase的权限模型。
权限问题
在一定程度上,我们可以认为BaaS是直接将数据和接口暴露给了最终用户(区别于只把数据和接口暴露给开发者),使用BAAS开发的应用的工作模式类似下面这种:
传统的服务接口的使用方式:
传统的开发方式,我们会开发一个SERVER程序负责跟后端其他服务接口和数据打交道,这个server运行在服务器端,可以很好的隔离app对接口和数据的非法访问,各种鉴权处理都是在SERVER端完成的。以微信为例,当个人用户登录微信后能看到哪些信息、不能看到哪些信息,是在SERVER端处理的。
当我们使用BAAS开发应用时,开发者不再需要开发SERVER程序,app直接调用BAAS提供的各种服务,那么BAAS就需要提供很好的机制来让开发者能开发出具备相同鉴权能力的应用。
当开发者不再开发SERVER后,尤其是像web这种可以认为所有源代码都是公开的应用,用户是可以看到app的所有代码和密钥之类的信息的,此时BAAS的服务将面临哪些问题需要解决呢?
从场景上来看
- BAAS需要区分授权API调用和匿名API调用
所谓授权API调用是指服务端能识别出该API调用者的身份;反之就是匿名调用,也就是没有提供任何凭据的API调用。通常大多数服务商是禁止匿名调用的,授权方式通常是提供一个API KEY。
这里面临的挑战是:由于没有SERVER这个中间层,API KEY只能配置到APP端,此时这个API KEY基本上可以认为是公开的(尤其web app),任何人都可以看到。一个任何人都可以拿到的API KEY如何进行安全的鉴权,这个API KEY的工作机制该如何设计?
- BAAS需要区分已登录用户和未登录用户的API调用
未登录用户的典型场景就是用户注册、登录、获取图形验证码等等。
这里有一个细微的差异需要考虑:匿名API调用和未登录用户的API调用。这里的匿名是指为提供API KEY的API调用。BAAS需要支持未登录的用户调用注册等接口,但是是否支持匿名API调用可以根据需要来调整。
从数据访问角度来看
- 访问public数据
public数据是否允许匿名API访问,是否允许未登录用户访问?如何设计鉴权?
- 访问私有数据(自己的或者别人的)
如何保证私有数据只有具备合法权限的用户才能访问到?
- BAAS服务间数据互访问(BAAS是由一系列服务组合起来工作的,如数据库API、存储API、用户API)
比如提供用户注册、登录等功能的auth服务需要读写user表。如何在保证auth服务能正常读写user表的同时,确保调用auth接口的用户不会任意篡改user表?
BAAS服务要提供能满足真实需要的服务能力,必需提供良好的鉴权机制,并开放给开发者使用。
Supabase当前解决方案
API鉴权
Supabase给API调用分了两种key:anon key、service key
-
anon key:是公开的key,给app使用,所有人可以拿到。所以anon key的权限是受限的。
-
service key:使用service key调用api可以做任何事情,不受限制。因此service key只能配置给BAAS内部服务使用,这些服务是服务商自己开发的,因此受授信的。
用户数据访问鉴权
Supabase主要依赖PostGREST基于pg的RLS(Row level security)的数据访问控制能力实现数据访问鉴权。参考《postgrest体验》。
为了配合PostgREST,Supabase内置了3种user role:anon、authenticated、service_role。
-
anon是用户未登录时使用的role。
-
authenticated是用户登录后进行数据操作时使用的role。
-
service_role是供其他服务使用的role,可以绕过RLS(感觉不是程序实现的,需要在创建这个role时设置为BYPASSRLS,从而是的RLS对该role不起作用)。
上面的anon和service_role和anon key、service key似乎可以相互呼应。
问题:key和role之间怎么呼应的?
postgrest检查role的方式是从jwt的载荷中获取的,kong中配置的anon key以及service key就是使用anon和service_role两个载荷创建的jwt token。需要使用jsonwebtoken.io之类的工具加下类似下面的载荷来生成:
# anon Payload:
{
"iss": "Supabase",
"iat": 1603968834,
"exp": 2550653634,
"aud": "",
"sub": "",
"role": "anon"
}
# service_role Payload:
{
"iss": "Supabase",
"iat": 1603968834,
"exp": 2550653634,
"aud": "",
"sub": "",
"role": "service_role"
}
JWTs in Supabase
-
anon key: This key is used to bypass the Supabase API gateway and can be used in your client-side code.
-
service role key: This key has super admin rights and can bypass your Row Level Security. Do not put it in your client-side code. Keep it private.
-
user specific jwts: These are tokens we issue to users who log into your project/service/website. It’s the modern equivalent of a session token, and can be used by a user to access content or permissions specific to them.
下一篇我们会详细介绍postgrest的anon、authenticated等角色的工作机制。