- 后端
- 工作流自动化
- 流程编排
- 低代码
【免费下载链接】elsa-core
The Workflow Engine for .NET
本文面向 Elsa 3 部署者与安全运维人员,系统讲解如何在不中断现有登录的前提下,将 Studio 从「直连 OpenID Connect」迁移到「Elsa Broker 外部认证」模式:涵盖模式选择、配置映射、8 步安全上线流程、回滚策略以及 Studio Server / WebAssembly 两种主机的差异处理。读完本文,你将掌握一套可复制、可验证、可回退的企业级 SSO 迁移方案。
1. 背景:两条截然不同的认证路径
Elsa Studio 目前支持三种互斥的认证提供方(Authentication:Provider):
OpenIdConnect:Studio 直接作为上游 OpenID Connect 提供方的 relying party,自行完成授权码交换与登录。ExternalAuthentication:Elsa Server 作为上游提供方的 relying party,代为完成认证后,向 Studio 颁发 Elsa 自身的凭证(即「Broker 代理登录」)。ElsaIdentity:Elsa 本地用户名/密码凭证,属于既有的直连集成。
Broker 模式的核心变化在于 Elsa.ExternalAuthentication 模块:Elsa Server 独占「上游 provider 重定向、回调、身份解析、权限解析、Elsa 凭证签发」这些环节,Studio 只负责展示登录方法选择器(Login Method chooser)并消费 Elsa 签发的一次性完成码(completion code)。从源码结构看,这一分工体现在 ExternalAuthenticationBroker.cs 中:Broker 同时依赖连接注册表、适配器、密钥解析器、外部身份解析器、权限授予解析器、状态存储、授权码存储、会话存储与令牌签发服务,构成一条完整的服务端代理链路。
2. 每个 Studio 主机只能选择一种模式
Authentication:Provider必须且只能设置为以下三者之一:
| 值 | 含义 |
|---|---|
OpenIdConnect | 既有直连集成(单 provider,Studio 直接对接) |
ExternalAuthentication | Broker 代理登录(本文迁移目标) |
ElsaIdentity | 既有 Elsa 本地凭证直连集成 |
严禁在同一个主机中同时注册直连 OpenID Connect 与 Broker 认证。模糊的启动配置会被直接拒绝,而不会隐式地「替你选一个模式」——这正是 studio-contract.md 中「启动失败条件」明确要求的:Broker 模式下若同时启用了直连 OIDC 处理器,启动即失败并给出可操作的配置错误提示。
3. 配置映射:把现有直连注册迁到 Broker
迁移的本质不是「改写旧配置」,而是「把旧配置的语义重新表达为一组新的部署资产」。下表是官方给出的完整映射关系:
现有Authentication:OpenIdConnect设置 | Broker 目标 |
|---|---|
Authority/MetadataAddress | 配置持有的连接adapterSettings.authority及 discovery 模式 |
ClientId | 连接adapterSettings.clientId(上游 client 注册) |
ClientSecret | 连接secretBindings.clientSecret;只能通过部署密钥配置复制该值,绝不可经由 API 或 UI |
AuthenticationScopes | 连接adapterSettings.scopes |
RequireHttpsMetadata | 保持安全的 discovery 默认值;任何不安全 trust 覆盖都需要显式的部署许可与特权确认 |
CallbackPath | 用 Elsa 固定的 Connection-ID 回调替换 provider 回调 |
SignedOutCallbackPath | 启用上游 logout 时,注册 Elsa 的上游 logout 回调 |
NameClaimType/RoleClaimType | 配置归一化 claim 投影与显式授权映射;上游角色不会自动成为 Elsa 权限 |
BackendApiScopes | 无直接映射;Studio 以 Elsa 签发的凭证调用 Elsa |
需要特别强调两个注册主体的区别:上游 client(属于 provider 连接)与Elsa Authentication Client(标识 Studio 对 Elsa Broker 的身份)是两份不同的注册。后者不授予任何 Elsa 权限,只负责持有 Studio 精确的回调、logout 回调、origin 与 return-path 注册。这一隔离在 ExternalAuthenticationOptions.cs 中体现为独立的AuthenticationClients配置集合——部署持有的 Broker 客户端与 Identity Provider 连接是两个完全独立的配置域。
4. Broker 的核心机制(源码级原理)
在动手迁移前,理解 Broker 的令牌流与安全不变量有助于你正确配置。Broker 主流程可归纳为四段(对应 ExternalAuthenticationBroker.cs):
- 发现:匿名端点
GET /external-authentication/login-methods返回 Login Method 列表,只包含 method key、kind、显示名、受信任图标 ID、排序、首选状态与 Elsa 持有的发起 URL——不返回adapter 设置、provider authority、上游 client ID、健康状态、密钥或远程图标(见 DiscoverLoginMethods.cs)。优选方法只是视觉元数据,客户端必须始终渲染显式选择器。 - 发起:Broker 校验 client 注册与
response_type=code、code_challenge_method=S256、回调精确匹配、return-path 白名单,然后为连接生成一次性事务并调用 adapter 构造上游授权请求。 - 回调:回调按「不可变逻辑 Connection Key」路由;Broker 原子取出事务、校验 material revision 与密钥代际指纹(generation fingerprint)后,调用 adapter 认证、解析外部身份、解析权限授予、建立外部会话,最后签发短生命周期、单次使用的完成码并携带 client state 重定向回 Studio。
- 兑换:Studio 以完成码 + PKCE verifier 兑换 Elsa access token 与 refresh token;兑换会校验 client(confidential 用 client secret 常量时间比对,public 用精确 origin)、code 单次性、回调、PKCE 与外部会话状态。
由此延伸出几条不可动摇的安全不变量:回调派生固定、confidential client 要求、S256 PKCE 强制、state/correlation/nonce 校验、签名与 audience/lifetime 校验、完成码单次性、密钥脱敏。管理界面不提供这些开关——任何连接或 Studio 配置都无法弱化它们。
另外注意「material revision」:连接被禁用、归档、material 变更(adapter 设置、密钥绑定身份/代际、未链接身份策略、defaultRoleIds、override 生命周期)都会使进行中的回调与后续 refresh 失效;仅做展示层修改不会打断流程。
5. 安全上线(8 步)
官方给出的零中断迁移顺序如下,每一步都刻意把「新增 Broker 资产」与「切换 Studio 模式」分离:
- 保持 Studio 处于
OpenIdConnect模式——迁移期间现有登录照常。 - 在 Elsa Server 添加 External Authentication 模块。
- 添加配置持有的 OpenID Connect 连接与部署持有的 Studio Authentication Client。
- 向上游 provider 注册 Elsa 的 provider 回调;暂时不要删除现有直连 Studio 回调。
- 分别在 Elsa Server 与 Studio Server 独立解析密钥——迁移全程不搬运、不暴露任何密钥。
- 在非生产环境测试连接并完成一次 Broker 登录。
- 仅修改
Authentication:Provider为ExternalAuthentication,重启 Studio 主机。 - 验证通过后,按你自己的轮换计划删除过时的直连回调与仅直连使用的密钥。
第 5 步的「独立解析密钥」正是secretBindings设计的核心:连接中只存放密钥绑定引用(配置键或 Elsa Secrets 引用),从不存放密钥值本身。绑定解析结果会生成一个不可逆的代际指纹(generation fingerprint),该指纹用于在回调时检测密钥是否在流程中途被更换——被更换则拒绝流程(见 ExternalAuthenticationBroker.cs 的指纹计算)。
6. 回滚
回滚同样简单:
将
Authentication:Provider恢复为OpenIdConnect,重启 Studio 即可。
因为 Broker 配置不会改写Authentication:OpenIdConnect段,也不会搬运其密钥,直连注册在你刻意退役之前始终保持可用。配合第 5 步「两个主机独立解析密钥」,回滚时旧直连密钥天然还在原位。
7. 主机差异:Server 与 WebAssembly
两种 Studio 主机在 Broker 模式下的安全模型截然不同,必须分别理解:
7.1 Studio Server(confidential 客户端)
- 在服务端完成 Broker code 交换,refresh 凭证保存在服务端会话中;
- 浏览器只拿到安全的 HTTP-only 会话 Cookie;
- 会话 Cookie 要求:名称为
ElsaStudio.ExternalAuthentication,HttpOnly = true,Secure = Always,SameSite = Lax,且浏览器代码不可读取任何 Elsa/provider token。
对应 Studio Server 配置片段(完整示例见 quickstart.md):
{ "Authentication": { "Provider": "ExternalAuthentication", "ExternalAuthentication": { "ClientId": "elsa-studio-server", "ClientSecret": "{from-secret-configuration}", "CallbackPath": "/authentication/external/callback", "LogoutCallbackPath": "/authentication/external/logout-callback" } } }7.2 Studio WebAssembly(public 客户端)
- 没有 client secret,必须使用 PKCE;
- 注册精确的浏览器 origin(不允许通配符 origin 与带凭据的跨源请求);
- 默认凭证存储为仅内存;
Session或Durable浏览器持久化是显式的、会触发安全警告的部署选择(默认内存存储意味着刷新页面后需要重新登录)。
{ "Authentication": { "Provider": "ExternalAuthentication", "ExternalAuthentication": { "ClientId": "elsa-studio-wasm", "CallbackPath": "/authentication/external/callback", "LogoutCallbackPath": "/authentication/external/logout-callback", "BrowserStorage": "Memory" } } }8. 关键配置参考:连接与 Authentication Client
迁移中你需要新增两类部署资产(以配置优先方式,详见 quickstart.md):
Authentication Client(标识 Studio):clientId、clientType(confidential/public)、精确callbackUris与logoutCallbackUris、allowedReturnPathPrefixes(Server)或allowedOrigins(WASM)、confidential 客户端的secretBinding。confidential client 密钥由部署密钥配置提供,示例如下:
Authentication__ExternalAuthentication__ClientSecret={strong-random-value}Identity Provider Connection(标识上游 provider):核心字段包括id(稳定记录 ID)、key(不可变逻辑 Connection Key,用于持久链接与长会话)、adapterType(v1 为openid-connect)、adapterSettings(mode: "discovery"、精确discoveryUrl、上游clientId、scopes、clientAuthenticationMethod)、secretBindings.clientSecret、unlinkedPolicy、claimProjection与upstreamLogoutMode。
回调地址由部署持有的外部基地址与不可变逻辑 Key 派生,必须在上游注册两个精确回调:
https://elsa.example/elsa/api/external-authentication/callback/contoso-workforce https://elsa.example/elsa/api/external-authentication/previews/callback/01JZCONTOSOOIDC000000000001第一个用于普通用户登录(按逻辑 Connection Key 路由),第二个用于管理员 Preview(按连接记录 ID 路由)。从源码看,回调路由确实以 Connection Key 为第一层标识(见 ExternalAuthenticationBroker.cs:回调先按 key 取事务并核对 key 归一化结果)。
密钥绑定有两种所有权:external(配置解析器,值只存在于部署密钥配置,Studio 只读)与managed(Elsa Secrets 桥,授权管理员可通过 Elsa 管理生命周期)。官方推荐单节点开发用内存存储;生产多节点必须启用外部认证 EF 持久化、共享 ASP.NET Core Data Protection 密钥,并为所有节点配置相同的HandleHashing:SharedKeyBase64(用openssl rand -base64 32生成,轮换会使持久化的外部 subject 哈希失效,需单独制定迁移计划)。
9. 验证清单与测试入口
迁移完成后,建议按以下顺序验证 Broker(官方验证清单):
GET /elsa/api/external-authentication/login-methods?clientId=elsa-studio-wasm确认contoso-workforce以首选方法返回,且不含discoveryUrl、adapter 设置、client ID、测试细节、远程图标或密钥数据,Studio 仍显示选择器;- 打开 Studio
/login,选择 Contoso 完成 provider 认证; - 确认 provider 只重定向到 Elsa 派生回调;Elsa 只以不透明完成码 + client state重定向 Studio;
- 确认完成码重放失败;
- 确认 Elsa access token 携带 Elsa Roles 产生的会话 ID 与权限;
- 禁用连接后,确认发起、pending 回调与外部 refresh 全部失败,而已签发的 access token 按其配置的过期时间自然失效。
仓库内还有可直接运行的针对性测试:
dotnet test test/unit/Elsa.ExternalAuthentication.UnitTests/Elsa.ExternalAuthentication.UnitTests.csproj dotnet test test/unit/Elsa.Identity.UnitTests/Elsa.Identity.UnitTests.csproj dotnet test test/integration/Elsa.ExternalAuthentication.IntegrationTests/Elsa.ExternalAuthentication.IntegrationTests.csproj dotnet test test/component/Elsa.Workflows.ComponentTests/Elsa.Workflows.ComponentTests.csproj dotnet build Elsa.sln功能规格中的可度量成功标准(如零 token/密钥出现在管理、发现、重定向、错误、测试、Preview、健康检查、日志与通知输出中)由自动化契约测试覆盖,详见 spec.md 的 Success Criteria 一节。
10. 常见安全默认值与运维边界
Broker 模式下许多安全参数有部署级默认值(见 ExternalAuthenticationOptions.cs):
- Broker 事务/完成码生命周期:10 分钟 / 1 分钟;Preview / 最大外部会话:10 分钟 / 8 小时;
- provider 必须 HTTPS,私网目标默认拒绝,最多跟随 3 次重定向且每跳重新校验,请求/连接超时 10 秒;
- 未链接身份策略默认
reject(未知身份直接拒绝并返回安全错误与关联 ID),也可显式选择create-user的 JIT 策略; - 上游 logout 默认
Disabled(可选UserChoice/Always),且 v1 的登录/登出均为 Elsa 发起; - 最终登录路径守卫(final-login-path guard)默认启用并要求恢复方法——防止管理操作误删最后一个正常登录路径导致锁死。
需要警惕的边界:上游 claim 必须经过归一化投影(allowlist + 大小上限),defaultRoleIds只在新用户创建时生效且要求操作者具备授权,matcher 只提议用户、从不选择角色或权限,Elsa Roles 始终是 Elsa 权限 claim 的唯一来源。更多示例与逐步操作,请继续阅读完整的 quickstart.md(含 Server 与 WebAssembly 的完整配置)、studio-contract.md(Studio 契约与菜单信息架构)与 runtime-contracts.md(扩展契约签名)。
- 后端
- 工作流自动化
- 流程编排
- 低代码
【免费下载链接】elsa-core
The Workflow Engine for .NET
相关推荐
Elsa Core 代码库关注点审计报告:外部认证 Broker 的风险、技术债与安全边界
Elsa Core 代码库关注点审计报告:外部认证 Broker 的风险、技术债与安全边界 导读 本文是 Elsa Core 仓库中 doc/codebase/
后端工作流自动化流程编排低代码Elsa Workflows 领域术语体系解析:从输出转换到用户任务与外部身份认证
Elsa Workflows 领域术语体系解析:从输出转换到用户任务与外部身份认证 导读 本文面向使用 Elsa Workflows 构建 .NET 工作流引擎
后端工作流自动化流程编排低代码Elsa Core 外部认证会话绑定:共享受保护状态与连接修订版本机制解析
Elsa Core 外部认证会话绑定:共享受保护状态与连接修订版本机制解析 导读 Elsa Core 的外部认证(External Authentication
后端工作流自动化流程编排低代码
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考