🇺🇸 Read in English: Self-Hosted Auth for Developers: Better Auth vs Authelia vs Supabase Auth
朋友的创业团队最近在给一个 Next.js 产品加登录。页面和业务 API 都有了,用户数据准备放进 Postgres,登录注册却还没定。他问我:“这三个项目都叫认证,为什么部署教程看起来完全不像一回事?”
这才是选型时最容易踩的坑。搜索“开源认证”,Better Auth、Authelia、Supabase Auth 经常挤在同一页结果里。可是把它们当成三个可以互相替换的登录组件,就像在“给厨房供水”时,把水龙头、楼里的总阀和已经接好管线的整套厨房放在一起比。它们确实都能参与“用户是谁”的判断,接入位置、后续责任却很不一样。
本文讨论的是给自己的应用写代码、接登录注册的小团队。你需要决定谁管理用户、会话放在哪里、业务数据怎么判断权限,而不是替公司采购员工统一登录平台。Auth0、Okta 那类托管服务替你运行身份基础设施;这里讨论的则是自己集成、自己部署或自行维护的路径。为了选对工具,先把“用户能登录”这件事拆开。
先看用户登录之后,谁替应用做决定
产品里一个用户输入邮箱和密码,系统确认身份,这叫认证。接下来他能不能看到某个项目、能不能修改别人的账单,是授权。中间还有会话:用户刷新页面后为什么仍然在线,失效后如何重新登录,多设备退出时怎么处理。这三件事可以放在一个框架里做,也可以由不同的层分担。
如果只看登录页,三种方案似乎都能完成任务。一旦用户登录后直接访问数据库、通过反向代理进入几套内部工具,或者在 Node 服务里处理复杂业务权限,差别马上出现。真正该问的是:身份结果要交给哪一层?你的代码、数据库策略,还是站在应用前面的入口网关?
把责任边界说清楚,再看表格才有意义。这里的“耦合”不等于坏事:有时紧密集成省掉大量连接代码,有时它会让迁移变得费劲。
| 方案 | 主要落点 | 与应用的关系 | 权限最自然的落点 | 更顺手的起点 |
|---|---|---|---|---|
| Better Auth | TypeScript 应用中的认证框架 | 和应用代码一起集成、维护 | 应用服务端及业务代码 | 已有 Next.js/Node 项目,想把登录掌握在代码里 |
| Authelia | 独立认证门户、代理前的访问控制与 OIDC 身份提供方 | 通常作为独立服务运行,应用或代理对接它 | 入口访问策略;应用内权限仍要自己处理 | 已有多套服务,需要统一入口和登录 |
| Supabase Auth | Supabase 后端的认证服务,可独立使用 | 通过 SDK/API 对接,和 Supabase Postgres、RLS 配合紧密 | 数据库 RLS 加应用业务规则 | 数据已经放在 Supabase,想让用户身份直接约束数据访问 |
注意表格第三列:不是“谁的功能多”,而是写业务代码的人以后去哪里找认证逻辑。Better Auth 的配置和扩展更贴近项目仓库;Authelia 的认证策略更多留在单独运行的服务及代理配置里;Supabase Auth 的身份会进入数据库访问链路。如果团队出故障时习惯先打开应用日志,选了一套放在代理层的方案,就得接受排查路径跟着变长。
Better Auth:登录逻辑想留在项目里
回到那个 Next.js 产品。它需要注册、登录、找回密码,往后或许会有双因素验证和团队空间。开发者希望同一份 TypeScript 项目里能看清认证流程,不想为了登录先养一套独立身份服务。Better Auth 在这里显得自然:它是面向 TypeScript 的认证与授权框架,采用插件化设计,官方提供双因素认证、组织、多租户等扩展方向。项目官网把它定位为通用框架,意思是它不限于 Next.js,但 Next.js/Node 开发者能在熟悉的代码环境里使用它。
这种选择的好处不是“从此不用管认证”。恰恰相反,你获得了把认证和产品代码放在一起演进的能力,也接下了部署、数据库、密钥、邮件发送、会话安全等工作。比如产品的用户表与团队表已经有明确设计,登录后要按团队角色限制某个 API。你可以在服务端拿到会话,再按业务规则判断;认证框架负责确认和传递身份,具体“谁能改这张发票”仍由应用负责。别把“有组织插件”误读成所有业务授权都自动完成。
对写代码的小团队而言,这种控制权很实在。需求从“邮箱登录”长出“邀请成员加入工作区”,认证的变更可以随应用代码审查、测试、部署。但每次部署应用,也可能碰到登录流程:数据库迁移是否成功,Cookie 配置是否符合实际域名,生产环境里的邮件链接是否正确,都是上线前应亲自验证的事。组件给你成熟的零件,组装和维护仍是团队的工作。
另一个常被忽略的条件是技术栈。如果你的核心服务不是 TypeScript,Better Auth 的自然优势会缩水。跨语言系统当然可以通过 HTTP 或其他协议围绕一个认证服务整合,但如果为了使用这个框架,硬要新建一个 Node 身份服务,再让其他语言的业务系统都绕过去,就需要重新估算复杂度。工具适合哪里,要看它落地后是不是顺着现有架构走。
Authelia:它守的是入口,不是你的用户表
现在换个场景。团队除了产品站点,还有监控面板、内部文档、管理后台,分别跑在不同容器里。有人想让大家登录一次,就能进这些服务;最好管理后台还能要求额外验证。这个问题更接近 Authelia 的主场。它作为独立的认证门户,可以与反向代理配合,在访问服务之前检查身份,也能作为 OpenID Connect 身份提供方供应用对接。官方文档描述了单点登录、访问控制策略和多因素验证等能力。
把它简单说成“给 Next.js 加登录的另一个库”会误导人。代理拦住未登录访问者,并不等于业务系统知道该把哪一张订单显示给他。请求可以被允许进入 /dashboard,可用户是否能查看另一个公司的数据,还得让应用获取可信身份、建立自己的用户映射,并在业务接口里做授权。入口认证解决的是“这人能不能进这扇门”;房间里哪些抽屉能打开,是另一道判断。
这里有个容易出问题的接法:看到代理转发了身份信息,就直接相信应用收到的任意请求头。若应用端口还能被外界绕过代理访问,攻击者就可能自己伪造那些头。正确做法是把代理到应用的信任边界封严,明确清理和注入身份头的责任;走 OIDC 时则按协议验证令牌及回调。具体实现要依照你使用的代理和应用架构测试,不要把“代理前面加了登录页”当成完整的权限系统。
Authelia 的独立部署也意味着独立运维。认证门户不可用时,靠它保护的入口可能一起受影响;反向代理规则、回调地址、证书、身份存储及备份都要有人负责。这些不是缺陷,而是选择把身份集中在基础设施层后的账单。若团队原本就有多套自托管工具、懂代理和容器,集中维护可能比给每个工具重复写登录更省心。反过来,只有一个面向用户的 Next.js 产品时,为它专门引入代理、门户和应用身份映射,通常不会比直接集成认证框架更简单。
也别把 Authelia 的单点登录和产品里的“组织空间”混为一谈。前者让同一个身份进入多套应用;后者关心同一套 SaaS 里的租户隔离、角色和数据范围。即便用了 Authelia,产品内部的成员邀请、项目归属和权限仍需设计。一个工具能保护门口,不代表它知道屋里每件东西属于谁。
Supabase Auth:用户身份和数据访问一起设计
再换一条路线。假设这个团队已经把应用数据放在 Supabase 的 Postgres 里,前端通过 Supabase SDK 访问部分数据,并准备用行级安全策略(RLS)约束每个用户可见的行。Supabase Auth 的优势这时就比较具体了:它负责用户登录与会话,通过 JWT 传递身份,数据请求带着用户令牌,Postgres 的 RLS 策略据此决定能看到什么。官方文档还说明,认证信息保存在项目数据库的专门 schema 中,可以与业务表建立关联。
这个组合省掉的是身份与数据层之间的接线工作。举个小例子:你有一张 notes 表,每条记录有归属用户。登录之后,前端请求自己的笔记。与其只在前端加 owner_id 过滤、再祈祷没人修改请求,不如在数据库里设置合适的 RLS 策略,让数据库基于当前用户身份过滤。前端过滤决定界面呈现,数据库策略决定用户究竟能访问哪些行。两者的安全职责不同。
但“用了 Supabase Auth”也不意味着 RLS 自动写好了。你要给每张暴露给客户端的数据表审视策略,检查插入、查询、更新、删除分别允许什么;服务端使用高权限凭据时,也要确认哪些请求绕过了普通用户的限制。实际项目中的管理操作、后台任务和跨租户报表,往往需要另外设计权限边界。认证完成后拿到用户 ID,只是授权设计的起点。
它并非只能用于完整的 Supabase 后端,官方文档也明确提到可以单独使用 Supabase Auth。不过,如果你既不打算用 Supabase 的数据库访问路径,也没有计划依赖其 RLS,只是想给原有 Node 服务加一套可控的登录,会发现自己仍要把身份与现有数据库、业务权限接起来。此时选它的理由应该是 SDK/API 的接入方式符合团队需求,而不是以为“自带 RLS”会替自己的数据库完成授权。
至于自托管,也要把词说准确。Supabase Auth 是 Supabase 平台的一部分,自托管 Supabase 所需维护的范围比在应用里装一个认证库更大。你管理的不只有登录接口,还包括相关数据库、服务配置、邮件等运行依赖。若团队已经有托管或自托管的 Supabase 项目,沿用 Auth 是顺水推舟;若为了一个登录框从零部署整套后端,先估算长期维护成本,别只看演示项目启动时很顺畅。
一个小问题,能把三种方案分开
选型会上,我会先问:“如果用户明天说他登录不了,你准备去哪里找原因?”答“看应用代码、会话和部署日志”的团队,通常该优先试 Better Auth;答“查反向代理、认证门户和 OIDC 对接”的团队,才更像在解决 Authelia 擅长的问题;答“查用户令牌、SDK 请求以及 RLS 策略”的团队,往往已经站在 Supabase Auth 的工作流里。
这个问题比功能清单有用,因为故障总会发生。邮件送达失败、会话在浏览器里丢失、回调域名写错、权限策略把用户挡在数据表外,看上去都像“登录坏了”,却分属不同系统。把排查能力也算进选型成本,比争论哪个项目星数更高更可靠。Better Auth 与 Authelia 的 GitHub 热度都很高,但星数只能说明关注度,无法回答哪个更适合你手上的登录链路。
还要问数据和身份谁先存在。如果项目已经使用 Supabase 的 Postgres 和客户端数据访问,优先评估 Supabase Auth,看看现有表与 RLS 能否按产品需求落实。若数据在自己的数据库里,应用也是 TypeScript 服务,Better Auth 通常是更直接的实验对象。若眼前真正的问题是多套应用缺统一入口,先画出域名、代理和身份流,再看 Authelia;不必强迫它承担单个产品内部的全部权限逻辑。
有时答案甚至不是三选一。已有多套内部工具的团队可能用 Authelia 守住管理入口,面向客户的 SaaS 产品仍用应用内认证。两条身份链路是否该打通,要根据实际用户群和运维能力决定,别因为“统一”听起来漂亮就提前把它们绑死。也不要在同一个客户登录流程里叠两套会话,只为了让架构图显得完整:用户退出、令牌刷新和权限变更会变得更难解释。
开始写代码前,先画一张请求流向图
不需要复杂图纸。把浏览器、Next.js/Node 应用、反向代理、认证服务、数据库画成方框,再画出一次注册、一次登录、一次读取私有数据分别经过哪里。写下每一步由谁验证身份、谁签发或持有会话、谁做最终权限判断。画到某个箭头说不清,就别急着拷贝接入示例。登录流程真正危险的地方,常常藏在两个组件交接时没人负责的那一小段。
随后做一个很小的验证:普通用户登录后只能读到自己的数据;退出后旧会话不能继续读;没有权限的用户即使绕过前端页面,直接请求 API 也拿不到别人的记录。若用代理方案,再验证应用不能被绕过代理直连;若用 Supabase,再检查客户端访问的表是否确实受 RLS 约束;若用 Better Auth,再检查生产域名和服务端会话的实际行为。这些测试比把“支持 MFA”“支持 SSO”勾满更早暴露架构错误。
最后别忘了自托管的代价并不写在许可证里。开源方案可以没有强制商业授权费,但你要安排升级、备份、密钥轮换、邮件投递和故障恢复。Better Auth 将工作更多留给应用团队,Authelia 把一部分压力放到入口基础设施,Supabase Auth 则让数据库策略和后端运行状态成为认证体验的一部分。省掉外部托管账单,不等于省掉维护责任。
那个朋友的团队最后该怎么选?如果他们仍是一个 Next.js 产品、数据在自管 Postgres、没有一排内部服务等着统一登录,我会先让他们用 Better Auth 做最小可用验证,同时把业务权限单独设计;若数据库已经迁到 Supabase,就把 Supabase Auth 和 RLS 放在一张图上一起验证;只有当“多套服务共用入口”成为真实需求时,才把 Authelia 提到桌面上。先确定身份该停在哪一层,再挑工具。这样选出来的不是看起来最强的认证项目,而是以后出了问题,你的团队知道该去哪儿修的那一个。
参考资料:Better Auth 官方介绍 · Authelia 官方站点 · Supabase Auth 官方文档



