企业客户的第一封邮件往往只有一句话:“我们的员工能用Okta登录吗?离职后能立刻停掉吗?” 很多团队为了回答这句话,绕了六周的弯路。他们给每张表加一个company_id字段,手写邀请邮件,然后才发现SAML有一堆自己的脾气。这篇内容把整条路径一次走完:组织、角色、资源层级、SSO,以及SCIM自动开通。 代码层面用的是theAuth,一个开源的TypeScript认证库(@glinr/theauth)。同时也要说清楚它在哪里停下、哪些部分必须由你自己的代码接手。有些缺口比功能本身更值得注意。 这是theAuth八篇指南中的第三篇。它可以独立阅读,所以你可以直接从这一篇开始。它建立在可用的登录之上(第一篇),不需要其他指南。 为人类构建产品?从第一篇开始。为AI代理构建?从第五篇开始。每篇指南都会链接到它所涉及概念的文档页面。 你最终会得到一个createTheAuth调用,把五层全部串起来,外加一份你必须自己添加的检查清单。 **先想清楚:你到底需不需要这一整套** 有一个诚实的边界要先划出来。如果你的产品只有个人用户、没有公司概念,那这一整套都不适用。直接跳过,用普通的登录方式就够了。 需要准备的东西不多:Node、一个TypeScript项目、一个数据库。示例用SQLite,方便在一个临时文件夹里跑起来。生产环境换成provider: 'postgres',配置写法在文档里有。 还需要一个能接收HTTP请求的入口。示例假设把theAuth适配器挂载在/api/theauth,这是文档里的默认挂载路径。任何框架都可以,适配器的搭建不在本篇范围内。 安装只有一行:npm install @glinr/theauth。 **从组织模块开始,别一次全上** 建议只先启用组织模块,之后再逐步扩展。org这个键决定了theauth.org是否存在。不加它,这个属性就是null,后面每一步调用都会失败。 初始化时传入三个参数:maxMembers设为100,maxOrgsPerUser设为5,allowCustomRoles设为true。这三个数字和文档里的默认值一致:每个组织100名成员、每个用户5个组织、自定义角色开启。写在代码里是为了把选择记录下来。 组织在实践中就是你的租户。slug只允许小写字母、数字和单个连字符。 创建组织时传入名称、slug、ownerId和metadata。ownerId对应的用户会自动成为成员,并带上owner角色。这一步省掉了一次你可能会忘记的写入。 这里有个命名陷阱要提醒。theAuth还有一个独立的tenant模块,用theauth.tenant.create创建。它存一条租户记录,AI代理可以携带一个tenantId。多租户文档页面说得很直接:租户是数据模型,不是执行层。authorize()不会比较租户,一个被暂停的租户也拦不住任何操作。 对于SaaS产品里的人类成员,用组织。租户模块可以当作给代理打的标签,在采取行动前自己检查agent.tenantId。 **邀请、角色和权限怎么落地** 邀请默认7天后过期,可以用invitationExpiryMs改。每个组织每小时的邀请数量上限用maxInvitationsPerHour控制,默认50。 发起邀请时传入orgId、邮箱、角色和invitedBy。之后在已登录用户的接受邀请处理器里,调用acceptInvitation完成加入。 日常管理是三个调用:getMembers取成员列表,updateMemberRole改角色,removeMember移除成员。 这些方法把用户id当作普通参数接收,比如invitedBy。路由处理器必须先确认调用者有权邀请,再去调用invite。 内置角色有四个。运行时检查只需要一次调用,比如在邀请路由前面放一个守卫,调用hasPermission判断members:invite。 你的产品会有内置角色没有命名的领域权限,计费角色是典型例子。可以按组织创建:传入角色名billing,权限列表为invoices:read和invoices:pay。然后在计费路由里调用hasPermission检查invoices:pay。权限字符串由你自己定义,theAuth负责存储,并回答关于它们的成员关系问题。 如果希望每个组织都锁死在这四个内置角色上,把allowCustomRoles设为false。对于支持人员需要仅凭角色名就能理解每个账号的产品,我会这么做。 组织路由也可以不写处理器。organization()插件会注册/auth/org/*路由,交给你的适配器来提供服务,其中每一个都要求用户已认证。

打开网易新闻 查看精彩图片