OpenWork 接入 Microsoft Entra ID:SAML SSO 与 SCIM 用户自动供给实战指南
【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork
本指南讲解如何将 Microsoft Entra ID(Azure Active Directory)连接到 OpenWork 组织,实现 SAML 单点登录(SSO)与 SCIM 用户/组自动供给。文章以 OpenWork 仓库中的官方接入文档为主体,结合源码级实现(Better Auth 插件接入、组织级路由与策略)深入展开,读完即可独立完成 Entra 企业应用的创建、SAML 双向对接、SCIM 供给配置、验证与故障排查全流程。
OpenWork 的 SSO/SCIM 架构:Better Auth 之上的组织级封装
OpenWork 的 SSO 与 SCIM 能力并不是从零实现的协议栈,而是基于 Better Auth 中直接导入了@better-auth/scim与@better-auth/sso两个插件(见该文件import { scim } from "@better-auth/scim"与import { sso } from "@better-auth/sso"),并在其上叠加了 SAML 响应策略、SCIM 去激活拦截、JIT 成员供给等自定义逻辑。
OpenWork 暴露给管理员与协议对端的表面路由如下:
| 区域 | OpenWork 表面 | 运行时行为 |
|---|---|---|
| SSO 管理 | /dashboard/sso、/v1/sso、/v1/sso/saml、/v1/sso/oidc | 每个组织只允许一条 SSO 连接,Owner 与安全管理员可创建或替换它 |
| SAML 回调 | /api/auth/sso/saml2/sp/acs/openwork-sso-<org-id> | OpenWork 先校验 SAML 响应策略,再由 Better Auth 消费响应 |
| SAML 元数据 | /api/auth/sso/saml2/sp/metadata?providerId=openwork-sso-<org-id> | 在 OpenWork 保存 SAML 连接后生成 |
| SSO 登录入口 | /sso/<org-slug> | 发起单组织的 SP 发起式 SSO,并跳转到 Entra |
| SCIM 管理 | /dashboard/scim、/v1/scim、/v1/scim/token | Owner 与安全管理员创建或轮换组织级 SCIM Bearer Token |
| SCIM 供给 | /api/auth/scim/v2 | 支持 SCIM 用户创建、更新与去供给 |
从路由实现看,ee/apps/den-api/src/routes/auth/index.ts 中对/api/auth/sso/saml2/callback/*与/api/auth/sso/saml2/sp/acs/*两个路径都挂载了samlResponsePolicyMiddleware(来自sso-saml-response-middleware.ts),这正是"OpenWork 先校验 SAML 响应策略、再交给 Better Auth"的实现位置。
OpenWork 对组织 SSO 强制执行以下 SAML 安全设置:
- 强制要求签名后的 SAML 断言(signed SAML assertions)。
- 仅通过组织专属的 provider ACS URL 接受 IdP 发起的 SAML。
- 强制要求 SAML 时间戳。
- 拒绝已弃用的 SAML 算法。
- SSO 登录会写入外部身份链接(external identity link)并执行组织成员的 JIT(Just-In-Time)创建。
- 对于被组织 SSO 或 SCIM 连接托管的用户,拒绝其使用邮箱/密码方式登录。
一个需要特别说明的边界:OpenWork 目前不支持 SCIM Group 对象供给。你可以将 Entra 用户和组分配给企业应用以控制范围,但必须保持 Entra 的组对象映射(group object mapping)处于关闭状态。
前置条件
在开始之前,请确认以下条件全部满足:
- 一个拥有安全配置权限的 OpenWork 组织 Owner 或管理员。
- 一个有权管理企业应用的 Microsoft Entra 账户。Microsoft 官方将此角色描述为 Cloud Application Administrator、Application Administrator,或 SSO 配置所用服务主体的 Owner。
- OpenWork 的公开 Web 与 Auth URL 必须是已定稿的 HTTPS URL。生产环境中,不应让 SAML 与浏览器 Auth Cookie 去校验临时的 HTTP 源(origin)。
- OpenWork 组织应在组织设置中提前配置好期望的邮箱域名(email domain),再将该域设为 SSO 强制域。
- OpenWork 组织必须已启用 SSO/Enterprise 权益(entitlement)。未启用时,OpenWork 会保持表单可编辑,但保存时会拒绝并提示
SSO / SAML requires an Enterprise plan。这一限制在源码的权益校验(ee/apps/den-api/src/entitlements.ts)链路中得到印证。
OpenWork Labs 测试租户参考值
若你在 OpenWork Labs 测试租户中演练,可参考以下值:
- Tenant ID:
2b853de0-b14b-4433-90be-cced1b963647 - OpenWork SSO 域名:
omaropenworklabs.onmicrosoft.com - 测试用户:
omar2@omaropenworklabs.onmicrosoft.comomar_openworklabs.com#EXT#@omaropenworklabs.onmicrosoft.com
- OpenWork 组织:
Omar Azure Test
文档记录(截至 2026 年 7 月 7 日):上述两个测试用户均已分配到 Entra 中的OpenWork Labs企业应用,且 OpenWork Cloud 组织具备保存 SSO 设置所需的 Enterprise 权益。
创建或选择 Entra 企业应用
- 打开 Microsoft Entra 管理中心。
- 进入Entra ID->Enterprise apps->All applications。
- 选择已有的 OpenWork 企业应用,或为 OpenWork 新建一个非库(non-gallery)企业应用。
- 在Users and groups下至少分配一个测试用户或测试组。
配置 SAML SSO
SAML 对接存在一个双向交接:OpenWork 需要先拿到 Entra 的 IdP 值才能保存连接,而 Entra 需要 OpenWork 生成的 ACS URL 才能完整测试 SAML。请严格按顺序操作。
- 在 Entra 企业应用中打开Single sign-on,选择SAML。
- 在 Entra SAML 页面复制以下 IdP 值:
- Microsoft Entra Identifier:填入 OpenWork 的IdP Issuer URL。
- Login URL:填入 OpenWork 的SAML Entry Point。
- Certificate (Base64):将 PEM 证书粘贴到 OpenWork 的IdP Certificate。
- 在 OpenWork 中打开Dashboard->SSO,选择SAML。
- 填写 OpenWork 字段:
- IdP Issuer URL:Entra 的Microsoft Entra Identifier。注意这是 IdP issuer,而不是 Entra 应用自身的 Identifier / Entity ID。
- Domain:应使用该 SSO 连接的邮箱域名,例如
example.com。 - SAML Entry Point:Entra 的Login URL。
- Audience URL:留空则使用 OpenWork Auth URL;或填写一个稳定的 Entity ID,并同步将其设置为 Entra Identifier。
- IdP Certificate:Entra 的 Base64 证书,以 PEM 文本形式粘贴。
- 在 OpenWork 中保存 SSO 连接。
- 对于
example.com这类自定义域名:先在 OpenWork 请求域名验证 TXT Token,发布到 DNS,再点击Verify domain。 - 对于以
.onmicrosoft.com结尾的 Microsoft 租户域名:OpenWork 会根据匹配的 Entra 租户 issuer 与 SAML entry point 直接完成域名验证,无需在 Microsoft 的onmicrosoft.com区域下发布 DNS 记录。
- 对于
- 复制 OpenWork 生成的值:ACS URL、Metadata URL、Sign-in URL。
- 回到 EntraSingle sign-on->Basic SAML Configuration,设置:
- Identifier (Entity ID):OpenWork 的 audience。若 OpenWork audience 留空,则使用部署文档或元数据中展示的 OpenWork Auth URL。不要在此处使用 Entra 的
https://sts.windows.net/.../issuer。 - Reply URL (Assertion Consumer Service URL):OpenWork 的ACS URL。
- Sign on URL:OpenWork 的Sign-in URL。
- Identifier (Entity ID):OpenWork 的 audience。若 OpenWork audience 留空,则使用部署文档或元数据中展示的 OpenWork Auth URL。不要在此处使用 Entra 的
- 保存 Entra SAML 配置。
- 在 EntraAttributes & Claims中确认 OpenWork 能收到:
email:用户邮箱,通常是user.mail,在mail为空的租户中回退到user.userprincipalname。displayName:用户显示名。- Name ID:类邮箱的稳定用户标识符。
- 使用已分配用户从 OpenWork 的
/sso/<org-slug>URL 或 Entra My Apps 磁贴测试。对于多组织用户,org slug、Entra 应用与 ACS URL 共同决定其进入哪个 OpenWork 组织。
OpenWork Labs 测试租户的 SAML 字段示例
- IdP Issuer URL:
https://sts.windows.net/2b853de0-b14b-4433-90be-cced1b963647/ - Domain:
omaropenworklabs.onmicrosoft.com - SAML Entry Point:
https://login.microsoftonline.com/2b853de0-b14b-4433-90be-cced1b963647/saml2 - Audience URL:留空,除非你同时设置了自定义 Entra Identifier。留空时,将 Entra 的Identifier (Entity ID)设为 OpenWork Auth URL,而不是
sts.windows.netissuer。 - IdP Certificate:粘贴 Entra 当前有效的 SAML 签名证书。
关于启用前必须测试的补充说明
仓库配套文档 packages/docs/cloud/sso-microsoft-entra.mdx 还补充了两个重要细节,建议一并执行:
- OpenWork 在域名验证完成、真实认证测试通过、并显式启用 SSO 之前,会一直将新 SSO 配置保持为禁用状态。配置期间请保留密码或其他恢复登录通道。
- SAML 签名要求
Signing Option为Sign SAML assertion、Signing Algorithm为SHA-256。若 Entra 只签名 response 而不签名 assertion,回调会以saml_error/Invalid SAML response失败——这与 OpenWork "强制签名断言"的策略一致。 - 启用流程:在 OpenWorkSettings → SSO选择Enable Config / Enable SSO,在测试对话框中执行SSO Login,完成 Microsoft 认证后确认Authentication test successful,再点击Enable SSO。测试链接有效期约 5 分钟;编辑过 SSO 配置后必须重新测试才能再次启用。
JIT 供给与角色边界
Entra SAML SSO 对已验证域名启用后,OpenWork 的标准登录流程会将具有该邮箱域名的用户路由到组织 SSO 流程。用户成功完成 SAML 登录后,OpenWork 会以默认Member角色 JIT 创建其组织成员身份。JIT 供给只发生在 SAML 认证成功之后;用相同域名创建邮箱/密码账户并不会把用户加入组织或产生 SCIM 托管身份。另外,OpenWork 不会把 SAML 属性(如role、groups、admin)转换为组织内的高权限角色——Owner/超级管理员需要在 OpenWork 内分配角色,所有权变更需走所有权转移流程。
配置 SCIM 用户与组供给
SCIM 管理入口与认证实现位于 ee/apps/den-api/src/routes/auth/scim.ts:该路由以scimBearerToken作为安全方案(缺失或无效时返回 401),并调用resolveScimProviderFromBearerToken依据 Bearer Token 解析对应的供给方,再通过syncExternalIdentityFromScimResource等函数同步外部身份。操作步骤如下:
- 在 OpenWork 打开Dashboard->SCIM。
- 复制SCIM base URL(通常以
/api/auth/scim/v2结尾)。 - 创建或轮换连接器 Token,并立即复制 Bearer Token。OpenWork 只在创建或轮换后展示一次完整 Token。
- 在 Entra 企业应用中打开Provisioning。
- 将Provisioning Mode设为Automatic。
- 在Admin Credentials下设置:
- Tenant URL:OpenWork 的SCIM base URL。
- Secret Token:OpenWork 的 SCIM Bearer Token。
- 点击Test Connection。
- 打开Mappings:
- 保持用户供给(user provisioning)开启。
- 当 Entra 组需要管理 OpenWork 团队时,启用组对象供给(group object provisioning)。
- 使用 OpenWork 可按其过滤的匹配属性,通常是
userName(映射自userPrincipalName或mail)。
- 在 OpenWork 中,若供给的组应创建并管理对应的 OpenWork 团队,则启用Create teams from SCIM groups;关闭该选项则只保留组元数据、不改变团队。
- 在Settings下选择范围(scope)。受控灰度发布时,只同步已分配(assigned)的用户与组。
- 在测试连接与映射都正确后,再打开Provisioning Status。
SCIM 生命周期与团队同步的补充要点
配套文档 packages/docs/cloud/scim-microsoft-entra.mdx 对上述流程做了更细的补充:
- 在 Entra 的Provision on demand中测试组供给时,请确保测试组内已有至少一个已分配测试用户,并在Selected users中显式勾选最多 5 名成员。Entra 的按需组流程对空组或未选成员时可能返回通用内部服务器错误(该错误可能发生在 Entra 向 OpenWork 发送组创建请求之前);Entra 的常规后台供给周期仍可同步空的已分配组。
- 正式开启定时供给后,供给是增量的:新分配的对象可能要到下一个周期才出现,请用 Entra 的Provisioning logs区分"待执行周期"与"操作失败"。
- SCIM 托管团队应在 Entra 侧变更,而不是在 OpenWork 内手工编辑;OpenWork 会把手动创建的团队与 IdP 托管的团队区分开。
- 若想通过 Entra 组授予组织
Admin角色,需要由 OpenWork Owner/超级管理员在团队管理界面显式审批该同步团队(Team Admin access),Entra 组名与 SAML 组属性本身不会授予提升权限。移除用户出组后,需等待供给成功并确认继承权限已消失。
验证清单
对接完成后,逐项核对:
- OpenWork 的
/sso/<org-slug>Sign-in URL 能跳转到 Entra,完成 SP 发起式 SSO。 - Entra My Apps 或测试启动能把 SAML response 投递到 OpenWork 生成的 ACS URL。
- 首次 SSO 登录会创建或更新 OpenWork 用户与组织成员。
- 当组织域要求 SSO 时,被托管用户使用邮箱/密码登录会被拒绝。
- Entra SCIMTest Connection成功。
- 供给一个已分配测试用户后,OpenWork 中创建了对应的用户与组织成员关系。
- 启用团队同步时,供给一个组会创建对应的 OpenWork 团队。
- 移除分配后,会保留一条断连的成员记录;只有当该用户没有其他有效组织成员关系时,OpenWork 才会删除其全局用户。
故障排查
| 症状 | 可能原因 | 修复 |
|---|---|---|
| Entra 提示 reply URL 无效 | Entra Reply URL 与 OpenWork 生成的 ACS URL 不匹配 | 保存 SAML 连接后,从 OpenWork 复制 ACS URL 粘贴到 Basic SAML Configuration |
Microsoft 对https://sts.windows.net/.../报AADSTS700016 | Entra 把 IdP issuer 当成了 SP Entity ID / 应用标识 | 将 EntraIdentifier (Entity ID)设为 OpenWork audience/auth URL,并在 OpenWork 重新保存 SSO 连接,使 AuthnRequest 使用 OpenWork SP Entity ID |
| SAML 登录因 audience 或 recipient 错误失败 | Entra Identifier、OpenWork Audience URL 或 ACS URL 不一致 | 保持 Entra Identifier 等于 OpenWork audience、Entra Reply URL 等于 OpenWork ACS URL |
| 更换证书后 SAML 登录失败 | OpenWork 仍保存旧 IdP 证书 | 将新的 Entra Base64 证书粘贴到 OpenWork 并重新保存 SAML 连接 |
IdP 发起登录失败,报unsolicited_response | 部署运行的是旧版 OpenWork,拒绝 IdP 发起的 SAML | 升级 OpenWork,或从 OpenWork 的/sso/<org-slug>Sign-in URL 发起登录 |
| SCIM 测试连接未授权 | Token 复制错误,或配置 Entra 后 Token 已被轮换 | 轮换 OpenWork SCIM Token,并同步更新 Entra 的 Secret Token |
| Entra 组供给失败 | OpenWork 尚不支持 SCIM Group 对象 | 关闭组对象映射,仅用组分配来控制用户供给范围 |
参考文档
- OpenWork 官方配套文档:Microsoft Entra SAML SSO 与 Microsoft Entra SCIM provisioning
- 认证与策略源码:ee/apps/den-api/src/auth.ts(Better Auth SSO/SCIM 插件接入)、ee/apps/den-api/src/routes/auth/scim.ts(SCIM 路由与 Token 鉴权)、ee/apps/den-api/src/routes/auth/index.ts(SAML 回调挂载 SAML 响应策略中间件)
- Microsoft:Enable SAML single sign-on for an enterprise application(详见 packages/docs/cloud/sso-microsoft-entra.mdx 内引用的微软官方文档)
- Microsoft:Manage automatic user account provisioning、Develop and plan provisioning for a SCIM endpoint、Customize provisioning attribute mappings
- Better Auth SSO 插件与 SCIM 插件官方文档
【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考