ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Mastra 集成 Supabase Auth:@mastra/auth-supabase 授权层实现与源码解析

Mastra 集成 Supabase Auth:@mastra/auth-supabase 授权层实现与源码解析 Mastra 集成 Supabase Authmastra/auth-supabase 授权层实现与源码解析【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra本文基于 Mastra 仓库中 auth/supabase/README.md 及其配套实现讲解mastra/auth-supabase包的用途、安装与配置方式并结合 auth/supabase/src/index.ts 的源码与 auth/supabase/src/index.test.ts 的测试用例剖析其令牌认证authenticateToken、默认授权策略authorizeUser以及自定义授权覆盖的完整机制帮助你在 Supabase Auth 已管理应用用户的前提下让同一套会话直接保护 Mastra 服务端点。1. 包定位让 Supabase 会话保护 Mastra 端点mastra/auth-supabase是 Mastra 授权层authorization layer的 Supabase 提供方provider。根据 auth/supabase/README.md 的说明它做两件事验证 Supabase access token将请求中携带的 Supabase 令牌交给supabase/supabase-js校验换取对应的 Supabase 用户暴露 Supabase 用户给 Mastra 授权层认证得到的用户对象会进入 Mastra 服务端的授权流程参与路径保护判断。适用场景非常明确你的应用已经使用 Supabase Auth 管理用户登录、注册、会话刷新都由 Supabase 完成此时不需要为 Mastra 再搭一套独立认证体系直接复用同一套 Supabase 会话来保护 Mastra 暴露的 API 端点即可。从源码结构看auth/supabase/src/index.ts该包只导出了一个类export class MastraAuthSupabase extends MastraAuthProviderUser { protected supabase: SupabaseClient; // ... }它继承自MastraAuthProvider基类定义见 packages/_internals/auth/src/provider/index.ts泛型参数为supabase/supabase-js的User类型即认证/授权流程中传递的用户对象就是标准的 Supabase User。2. 安装与前置条件安装命令来自 auth/supabase/README.mdnpm install mastra/auth-supabase运行环境约束可从 auth/supabase/package.json 确认要求 Node.js 22.13.0运行时依赖为supabase/supabase-js^2.110.9令牌校验与数据库查询都通过该官方 SDK 完成包采用双格式导出ESM 的dist/index.js与 CJS 的dist/index.cjs见 package.json 的 exports 字段可按项目模块类型导入。前置条件在启动 Mastra 之前需要准备好两个 Supabase 凭据README 中的 SetSUPABASE_URLandSUPABASE_ANON_KEYbefore starting Mastra环境变量含义获取位置SUPABASE_URLSupabase 项目的 URLSupabase 控制台项目设置SUPABASE_ANON_KEYSupabase anon 密钥客户端公开密钥Supabase 控制台项目设置3. 基本用法接入 Mastra 服务端 authREADME 给出的标准接入方式是在new Mastra(...)的server.auth中实例化MastraAuthSupabaseimport { Mastra } from mastra/core/mastra; import { MastraAuthSupabase } from mastra/auth-supabase; export const mastra new Mastra({ server: { auth: new MastraAuthSupabase({ url: process.env.SUPABASE_URL, anonKey: process.env.SUPABASE_ANON_KEY, }), }, });对应仓库内的参考文档还包括 docs/src/content/en/integrations/auth/supabase.mdx集成指南与 docs/src/content/en/reference/auth/supabase.mdxProvider 参考。3.1 构造函数凭据解析与失败即抛错auth/supabase/src/index.ts 的构造函数逻辑constructor(options?: MastraAuthSupabaseOptions) { super({ name: options?.name ?? supabase }); const supabaseUrl options?.url ?? process.env.SUPABASE_URL; const supabaseAnonKey options?.anonKey ?? process.env.SUPABASE_ANON_KEY; if (!supabaseUrl || !supabaseAnonKey) { throw new Error( Supabase URL and anon key are required, please provide them in the options or set the environment variables SUPABASE_URL and SUPABASE_ANON_KEY, ); } this.supabase createClient(supabaseUrl, supabaseAnonKey); this.registerOptions(options); }要点双通道凭据解析优先使用显式传入的options.url/options.anonKey缺省时回退到环境变量SUPABASE_URL/SUPABASE_ANON_KEY。因此new MastraAuthSupabase()无参构造是可行的前提是环境变量已设置测试 src/index.test.ts 专门验证了这条路径启动期快速失败两个凭据都缺失时直接抛出错误。这意味着问题会在应用启动阶段暴露而不是在第一个请求到达时才失败name默认为supabase作为 Mastra 组件名用于日志与组件标识基类构造时传给MastraBase见 provider/index.tsregisterOptions(options)将可选的authorizeUser、mapUserToResourceId、protected、public等选项注册到基类实例上见 provider/index.ts这是后文自定义授权能够生效的机制基础。3.2 可选配置项继承自MastraAuthProviderOptions从 packages/_internals/auth/src/provider/index.ts 的MastraAuthProviderOptions定义看MastraAuthSupabase的构造参数除了 Supabase 特有的url/anonKey外还支持所有授权提供方通用的选项选项类型说明namestring?组件名默认supabaseauthorizeUserAuthorizeUserFnTUser?自定义授权函数覆盖默认的isAdmin查询逻辑mapUserToResourceId(user) string \| null \| undefined将认证用户映射为 memory/thread 作用域用的资源 IDprotected(RegExp \| string \| [string, Methods \| Methods[]])[]需要保护的端点路径规则public同上公开端点路径规则路径规则中Methods取值定义在 packages/_internals/auth/src/types/index.tsGET | POST | PUT | DELETE | PATCH | ALL。4. 认证流程authenticateTokenasync authenticateToken(token: string): PromiseUser | null { const { data, error } await this.supabase.auth.getUser(token); if (error) { return null; } return data.user; }来源auth/supabase/src/index.ts入参token是 Mastra 服务端从请求中提取的 access token内部调用supabase.auth.getUser(token)向 Supabase Auth 发起在线校验成功返回完整的 SupabaseUser对象包含id、email、user_metadata等字段失败令牌无效、过期或网络错误返回null而不抛异常——由上层 Mastra 授权流程将null解释为未认证请求将被拒绝。测试 src/index.test.ts 对两条路径都有覆盖有效 token 返回 mock 用户对象且断言getUser确实以该 token 为参数被调用无效 token 返回null。需要注意的一点该校验是每次请求实时查询 Supabase Auth本包自身不做本地令牌缓存也不解析 JWT 签名——令牌有效性完全委托给 Supabase 服务端。5. 默认授权策略查询users表的isAdmin字段这是该包最有行为约定属性的部分。默认的authorizeUser实现auth/supabase/src/index.tsasync authorizeUser(user: User) { // Get user data from Supabase const { data, error } await this.supabase .from(users) .select(isAdmin) .eq(id, user?.id) .single(); if (error) { return false; } const isAdmin data?.isAdmin; // Check permissions based on role return isAdmin; }由此可以得出三条使用前提与行为约定Supabase 项目中必须存在名为users的数据表且该表主键列id与 Supabase Auth 的用户 ID 对应并包含一个布尔列isAdmin授权 是否管理员请求路径是否放行取决于该用户行上isAdmin的真值。非管理员isAdmin: false会被授权层拒绝查询失败一律拒绝fail-closed数据库查询出现任何错误表不存在、RLS 拒绝读取等都返回false而不是放行。测试用例 src/index.test.ts 精确验证了这个行为序列管理员用户断言查询链from(users)→select(isAdmin)→eq(id, user.id)被依次调用且结果为true非管理员用户isAdmin: false返回false数据库错误single返回 error返回false。另外注意这里使用的是anon key 客户端查询业务表因此users表必须允许该查询路径可读例如针对 anon 角色的 RLS 策略若 RLS 未放行error分支会命中所有用户都会被授权层拒绝——这是部署时最容易踩的坑建议先手工验证 anon key 下select isAdmin from users where id ...是否可读。6. 覆盖授权逻辑通过authorizeUser选项定制默认的按isAdmin列判断在很多场景并不适用例如权限来自user_metadata、角色存在其他表、或需要按路径细分权限。基类MastraAuthProvider支持在构造时传入authorizeUser函数直接覆盖默认实现registerOptions会将其绑定到实例provider/index.ts。测试 src/index.test.ts 给出了一个完整的可运行示例const supabase new MastraAuthSupabase({ async authorizeUser(user: User): Promiseboolean { // 自定义授权逻辑检查特定权限 return user?.permissions?.includes(admin) ?? false; }, }); // 有 admin 权限 - true await supabase.authorizeUser({ sub: user123, permissions: [admin] }); // 只有 read 权限 - false await supabase.authorizeUser({ sub: user456, permissions: [read] }); // 无 permissions 字段 - false await supabase.authorizeUser({ sub: user789 });可见覆盖后的函数签名接收认证得到的User对象并返回Promiseboolean | boolean完全脱离了对users表isAdmin列的依赖。如果你的权限模型就是 Supabase Auth 的 metadata这是最轻量的定制方式无需继承类、无需额外数据库查询。7. 在 Mastra 服务端中的位置MastraAuthSupabase最终作为IMastraAuthProvider被server.auth接收。从 packages/core/src/server/auth.ts 看MastraAuthProvider等类型是从内部 auth 包转出给 core 使用的公共 API提供方需要实现的两个核心抽象方法是authenticateToken与authorizeUser见 provider/index.tsMastraAuthSupabase恰好一一实现请求到达受保护路径 → Mastra 服务端提取 tokenauthenticateToken(token)用 Supabase Auth 校验令牌得到User或nullauthorizeUser(user)按默认isAdmin策略或你自定义的策略决定放行与否。当你的 Mastra 实例同时组合多个授权提供方时例如 Supabase 另一个 SSO它们会被CompositeAuth包装按顺序尝试各提供方的authenticateToken任一成功即视为已认证见 provider/index.ts此时mapUserToResourceId会被自动代理到真正完成认证的那个提供方。8. 小结与核对清单mastra/auth-supabase的实现非常薄职责边界清晰认证委托给 Supabase Auth授权默认读取users.isAdmin其余策略全部开放定制。接入前建议按以下清单核对已安装mastra/auth-supabaseNode.js 版本满足 22.13.0SUPABASE_URL与SUPABASE_ANON_KEY已设置环境变量或构造参数二选一即可缺一即启动报错走默认授权时Supabase 中存在users表含id与isAdmin列且 anon key 可读需要非管理员语义的权限模型时已通过authorizeUser选项覆盖默认逻辑需要按路径细分公开/保护端点时已配置public/protected规则。相关入口文件汇总文件说明auth/supabase/README.md包说明安装、用法、文档索引auth/supabase/src/index.tsMastraAuthSupabase完整实现auth/supabase/src/index.test.ts构造函数/认证/授权/自定义覆盖的测试用例auth/supabase/package.json依赖、Node 版本与导出格式auth/supabase/CHANGELOG.md版本历史packages/_internals/auth/src/provider/index.tsMastraAuthProvider基类与通用选项定义docs/src/content/en/integrations/auth/supabase.mdx仓库内集成指南文档docs/src/content/en/reference/auth/supabase.mdx仓库内 Provider API 参考文档【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表