开源身份认证和授权解决方案
前言⌗
在考虑迁移单体应用到 Go 微服务时,发现身份认证是一个比较棘手的问题。调研了很多网关层面的身份认证解决方案,同时关注了一些开源项目,但是实际部署使用起来总觉得不是那么的顺心,
直到我发现了 ZITADEL。这是一个瑞士的团队基于 Golang 开发的云原生身份认证服务。经过研究和本地部署尝试后,不得不说该项目的完善程度相对较高了,而且是产品化思维主导开发的。无论对于开发者还是最终用户来说用户体验都可以媲美大型商业 IDaaS。例如国内的 Authing。
该项目成立于 2019 年,社区比较活跃,我自己部署和使用后也尝试参与到开源项目中,例如贡献汉化语言包,修复语言切换时的问题等。
功能⌗
- 身份管理(通过 组织的抽象模式来实现 EIAM 和 CIAM)
- 支持 RESTful、gRPC
- SDK
- 授权管理
- 项目管理
- 应用管理
- 跨组织、项目授权用户
- Passwordless(FaceID,TouchID 和 Key 等)
- Multifactor Authentication(FaceID,TouchID,Key 和 OTP 等)
- 用户自定义元数据
- 用户身份认证流程
概念⌗
Instance⌗
在 ZITADEL 中 Instance 的抽象层最高,可以理解成多租户的模型,例如每个公司可以是一个 Instance。在 Instance 中可以可以管理多个组织,同时也可以设置外部 IDP,密码复杂度,用户锁定策略,Passwordless 和 MFA 策略。
Organizations⌗
组织是对用户的一层抽象,用于管理和区分用户作用范围,例如对于企业来说,可能有 B 端客户和 C 端客户,那么可以将这些用户放在不同的组织中,同时自己内部系统的认证和授权再另外创建一个独立的组织。
组织也可以自定义外部 IDP 和品牌化身份认证 UI,以及覆盖 Instance 中的一些安全设置。
Actions and Flows⌗
这部分适用于设置用户身份验证后的触发流程和动作。
Domains⌗
组织的名称是域名中的一部分,而用户登录时需要使用用户名加上域名的方式进行登录,有点想电子邮箱地址。
例如:公司名叫 Betterde,这是一个 Instance,我们再创建一个内部人员 Internal 组织,那么这个组织下的用户登录时的用户名就是 [email protected]。
User⌗
用户就是我们理解的普通用户,可以在项目中对用户进行授权,如果用户在项目中没有授权,则无法在项目下的应用中通过 OAuth 流程进行登录。
也就是说,即使用户在组织中注册了信息,这时候依然无法登录的,需要管理人员在 Consule UI 中对用户所需要访问的应用进行授权,授权是指授予用户角色。当用户登录后会在 ID Token 中携带用户的在项目中的角色信息,用于后端服务的鉴权。
Service User⌗
用于后端服务之间通信的用户身份验证,例如在跨公司的服务调用时,需要身份验证的话,可以创建一个 Service User。
项目⌗
项目是对应用的抽象,那么为什么需要这样的抽象层呢?在实际的公司项目中,我们往往会将一个项目分为前端和后端,甚至是原生 APP。而这些对于用户来说是一个应用。通过这种方式可以更好的管理用户授权和同一项目不同端的应用。
应用⌗
这里的应用就是我们理解的 Web App、Native App 和 Service API,我们可以针对应用的不同类型设置不同的授权方式,以及 Token 的设置。
在现有系统中集成⌗
只要系统支持 OIDC 的方式,就能够使用 ZITADEL 作为外部 IDP 进行身份认证,例如 MiniO。
MinIO 集成 ZITADEL⌗
先看一下配置后的效果:
配置信息参考:
注意: Claim Name 的配置非常重要,因为 MinIO 与 ZITADEL 存在兼容性问题,所有我们这里不能通过角色来进行授权,只能通过 ZITADEL 的用户 ID,也就是
sub
字段来获取用户信息。同时还要在 MinIO 中为用户创建对应的 IAM Policy 并设置上对应的访问权限。
在 APISIX 中使用 OIDC⌗
APISIX Gateway 是支持 OIDC 的,通过 OIDC 插件可以由 API Gateway 实现集中身份验证,这样对于后端的服务来说,就不需要每个服务中都实现身份验证的逻辑了。后端只需要关注业务逻辑本身,这样降低了开发人员的心智负担!
APISIX 的 OIDC 插件支持两种自省模式:
- 令牌自省:通过请求 IDaaS 服务的 Introspection Endpoint 来自省,获取用户信息,并将用户信息进行 Base64 编码后附加到
X-Userinfo
请求头中; - 公钥自省:APISIX 通过公钥对 Access Token 或 ID Token 进行验签和有效期校验,但是不会将 Token 中包含的信息附加到请求头中,需要后端自行从 Token 中解析。
自省流程如下图所示:
类似项目⌗
- Hydra(开源):https://www.ory.sh/hydra
- Logto(开源):https://logto.io
- Dex(开源): https://dexidp.io
- Keycloak(开源): https://www.keycloak.org
- Authing(闭源):https://www.authing.cn
总结⌗
因为感兴趣它的设计和实现,我阅读了 ZITADEL 的源码,他们的技术栈让我眼前一亮,后端采用 gRPC 再通过 gRPC-Gateway 代理支持 RESTFul API 的方式。
前端也是采用 gRPC-Web 的方式与后端交互,这一点让我比较惊讶。这种方式虽然之前在网上看到过,但是因为当时处于 Beta 版。没想到已经有团队应用到生产环境中了!
研读代码后,确实学到了很多,后面考虑在项目中使用同样的技术栈来构建后端服务和通过 Proto 文件生成对应的文档和前后端代码。
I hope this is helpful, Happy hacking…