十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenWork Den API 认证路由模块解析:Better Auth 挂载、桌面登录交接与 SCIM 供给实现

OpenWork Den API 认证路由模块解析:Better Auth 挂载、桌面登录交接与 SCIM 供给实现 OpenWork Den API 认证路由模块解析Better Auth 挂载、桌面登录交接与 SCIM 供给实现【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork本文围绕 OpenWork 开源仓库中 ee/apps/den-api/src/routes/auth/README.md 所定义的认证路由目录展开剖析auth/目录在 Den API 中的定位、/api/auth/*与/v1/auth/desktop-handoff*两大 HTTP 表面的职责边界并结合源码说明 Better Auth 请求转发、短时桌面交接授权handoff grant、MCP OAuth 参数标准化、SCIM 供给等关键实现。读完本文你将掌握 OpenWork 认证面Authentication的完整路由拓扑、桌面端与网页端会话交接的底层原理以及如何在该目录下扩展新的认证相关端点。目录定位认证相关的 HTTP 表面在 Den API 服务ee/apps/den-api中src/routes/auth/目录被 README 明确界定为owning authentication-related HTTP surfaces即所有认证相关 HTTP 表面的归属地。目录当前包含四个文件文件职责index.ts将 Better Auth 挂载到/api/auth/*并注册认证专属的路由组OAuth 发现、动态客户端注册、登录选项、初始管理员 bootstrap 等desktop-handoff.ts桌面端登录交接流程挂在/v1/auth/desktop-handoff*下oauth-redirect.tsOAuth 授权端点响应重定向规范化scim.tsSCIMRFC 7644用户/组供给端点README 同时划定了目录边界新的认证相关自定义端点应放入本目录而不是me/或org/目录浏览器认证路由在无强烈理由时保持通过 Better Auth 挂载不做包裹改写。路由挂载总览路由注册统一在 index.ts 的 registerAuthRoutes 中完成入口挂载到 Hono 应用后按序注册注册 SCIM 认证路由registerScimAuthRoutes为 SAML 回调路径挂载响应策略中间件/api/auth/sso/saml2/callback/*与/api/auth/sso/saml2/sp/acs/*注册 OAuth 2.0 / OIDC 发现端点RFC 8414 与 OpenID Connect Discovery 1.0注册 RFC 7591 动态客户端注册端点注册初始管理员 bootstrap 状态/校验端点注册登录选项解析端点/v1/auth/login-options以app.on([GET,POST,PUT,PATCH,DELETE], /api/auth/*, ...)兜底转发 Better Auth 全部流程注册桌面交接路由registerDesktopAuthRoutes。其中第 7 步是核心handleAuthRequest最终调用auth.handler(c.req.raw)把进入/api/auth/*的请求原样交给 Better Auth 实例处理这也是 README Current responsibilities 中第一条职责的直接体现。核心职责一转发 Better Auth 请求代理路径解析与请求重写getBetterAuthProxyPathindex.ts将/api/auth前缀剥离得到 Better Auth 内部的路径如/sign-in/email、/oauth2/token、/sso/callback/xxx后续所有策略判断都基于这个代理路径展开。在转发前handleAuthRequest会执行一系列前置处理index.tsOAuth token 限流对POST /oauth2/token请求先做速率检查命中限流时记录日志并直接返回响应被拒绝的畸形请求也会消耗失败预算避免绕过宽松的尝试桶MCP OAuth 请求标准化调用normalizeMcpOAuthRequest见下文组织 SSO 回调授权识别/sso/callback/{providerId}OIDC与/sso/saml2/sp/acs/{providerId}SAML路径通过authorizeOrganizationSsoCallback校验未启用 SSO 时返回 403邀请注册放行isInvitationSignupAllowed校验?invite参数与待处理邀请是否匹配用于单组织模式下的邀请注册豁免邮箱密码锁定检查readEmailSignInAttempt/getEmailPasswordLockoutResponse在密码登录前检查是否因多次失败被锁定单组织模式守卫getSingleOrgAuthGuardResponse对组织创建、邮箱注册、密码登录、切换组织等操作施加策略详见下文密码策略链依次执行密码策略、弱密码、已泄露密码breach screening三道校验分别返回对应响应登出兜底对POST /api/auth/sign-out先显式撤销 Bearer 会话桌面端不使用 cookie再交给 Better Auth 处理保证浏览器端 cookie 清理的幂等行为不被破坏。单组织模式single_org策略从源码可以看到env.orgMode single_org时启用的守卫逻辑index.tsPOST /api/auth/organization/create一律返回 409single_org_mode邮箱注册若违反组织邮箱注册策略则返回 403singleOrgEmailSignupPolicyResponse邮箱密码登录时若组织已配置 SSO返回 403single_org_sso_required并携带signInPath切换活跃组织/organization/set-active只允许切到当前活跃组织或该组织的 slug。登录选项解析端点/v1/auth/login-options这是一个面向登录页的确定性路由解析接口index.ts给定邮箱返回下一步认证方式。nextStep取值为sso/google/github/password/new_account之一解析优先级为SSO Google 密码 GitHub 兼容 新建账号。该端点具备完整的反枚举与限流设计校验参数email并归一化与可选invite先清空残留的登录会话 cookie执行 bot 防护校验verifyBotProtection三级限流键loginOptionsRateLimitKeysIP 与邮箱维度20 次/分钟域名维度120 次/10 分钟为容纳团队同时登录的突发未注册地址额外走30 次/10 分钟的miss桶专门限制账号枚举返回体中含allowPublicSignup、allowInvitationSignupSSO 场景下还附带organizationSlug、signInPath、signInUrl。初始管理员 bootstrap私有化部署场景下通过两个端点完成首个管理员账号的设置index.tsGET /v1/auth/bootstrap/status返回available/complete/unavailable三种状态且不暴露已配置管理员邮箱POST /v1/auth/bootstrap/verify提交管理员邮箱与一次性运维码校验通过后签发短时 setup grant携带expiresAt该端点按邮箱限流5 次/5 分钟超限返回 429 与Retry-After。bootstrap grant 随后通过authorizeInitialAdminBootstrapSignup注入到邮箱注册请求中放行首个管理员创建并在注册完成后由completeInitialAdminBootstrapSignup收尾。核心职责二创建短时桌面交接授权桌面端Desktop App与网页端共享同一账号体系但桌面端不依赖浏览器 cookie。desktop-handoff.ts实现了网页登录 → 桌面登录的交接流程包含三个端点registerDesktopAuthRoutes。创建 grantPOST /v1/auth/desktop-handoff要求调用方已登录userSessionRoute() Bearer 会话请求体字段如下字段类型说明nextstring≤128可选交接客户端的延续提示desktopSchemestring固定openwork注册的 OpenWork 桌面 URL schemereturnUrlstring≤2048可选多组织 Cloud 实例下经服务端校验后返回的 HTTPS 网页回跳 URL创建逻辑desktop-handoff.ts若提供了returnUrl调用resolveApprovedWebHandoffReturnUrl做服务端校验仅接受https:、无凭据/哈希、路径为/或/signin、且来源必须精确等于配置的 gateway origin 或组织内云沙箱的签名预览 origin拒绝后缀匹配防攻击者控制来源校验失败返回 400invalid_return_url生成randomBytes(24).toString(base64url)作为 grant有效期5 分钟Date.now() 5 * 60 * 1000连同user_id、session_token写入DesktopHandoffGrantTable解析桌面端可用的 Den API 基地址resolveDesktopDenBaseUrl支持desktopDenBaseUrl配置或从 webUrl 推导/api/den代理路径构建深链openwork://den-auth?grant...denBaseUrl...返回给调用方。查询状态POST /v1/auth/desktop-handoff/status公开端点按 grant 查询其状态desktop-handoff.ts返回pending/consumed/unknown三种状态绝不返回会话令牌或用户详情。该端点按handoff:handoff-status限流240 次/分钟防止被用于暴力枚举 grant。交换授权POST /v1/auth/desktop-handoff/exchange核心职责三将有效 grant 交换为会话令牌。交换逻辑desktop-handoff.ts在数据库事务中完成联表查询DesktopHandoffGrantTable×AuthSessionTable×AuthUserTable条件为 grant 未消费consumed_at IS NULL、grant 未过期、关联 session 未过期立即执行UPDATE ... SET consumed_at now原子消费回查确认消费行归属本次claimed校验防止并发请求重复领取同一 grant任一步失败则整体回滚返回 404grant_not_found链接缺失、过期或已被使用。交换成功后还会附带组织上下文desktop-handoff.ts解析用户组织并返回organization: { id, slug, name }多组织模式下若无组织则自动创建个人组织以及connectEnabled基于组织元数据与 MCP 连接门控配置判断避免桌面端在交接后立刻竞态调用/v1/me/orgs。MCP OAuth 参数标准化与发现端点README 将注册认证专属路由组列为index.ts的职责之一其中最重要的一块是面向 MCP 客户端的 OAuth 兼容层。资源resource参数归一化normalizeMcpOAuthRequestindex.ts拦截/oauth2/authorize与/oauth2/token两个端点仅当请求 scope 含mcp:read/mcp:write或已注册客户端带 MCP scope 时才介入resource参数必须恰好一个且须为部署可识别的受保护资源通过normalizeMcpOAuthResource归一化见 auth.ts否则返回 400invalid_target对grant_typerefresh_token且缺失resource的请求默认填充DEN_MCP_OAUTH_RESOURCEMCP 公开场景下 audience 唯一补齐不影响安全性同时保证 audience 绑定。OAuth 发现与注册端点registerAuthRoutes 注册了GET /api/auth/.well-known/oauth-authorization-server与GET /.well-known/oauth-authorization-serverRFC 8414 授权服务器元数据GET /api/auth/.well-known/openid-configuration与GET /.well-known/openid-configurationOIDC Discovery 1.0POST /register与POST /api/auth/oauth2/registerRFC 7591 动态客户端注册。其中授权服务器元数据会把authorization_response_iss_parameter_supported置为falsemakeAuthorizationResponseIssuerOptional使客户端对iss参数缺失保持宽容——Better Auth 仅在部分兼容路径上返回 RFC 9207 的iss动态注册则先经rewriteMcpClientRegistrationRequest校验 redirect URI 与 scope 归一化再交给授权服务器。授权端点重定向规范化GET /api/auth/oauth2/authorize由 oauth-redirect.ts 的normalizeOAuthAuthorizeRedirect收尾Better Auth 对 fetch 风格请求返回 JSON 重定向信封{ redirect: true, url }而 OAuth 授权端点必须驱动用户代理跳转因此将此类 JSON 信封统一改写为标准 302携带原始location。SCIM 供给路由scim.ts 在/api/auth/scim/*下提供 RFC 7644 供给能力全部端点使用 SCIM bearer tokensecurity: [{ scimBearerToken: [] }]认证并以application/scimjson响应元数据发现GET /v2/Schemas、GET /v2/Schemas/urn:...:Group、GET /v2/ResourceTypes、GET /v2/ResourceTypes/Group组管理GET/POST /v2/Groups列表支持filterdisplayName/externalId 等值、startIndex、count分页、GET/PUT/PATCH/DELETE /v2/Groups/:groupIdPATCH 支持 RFC 7644 PatchOp 的 add/remove/replace用户供给POST /v2/Users、PUT/PATCH /v2/Users/:userId、DELETE /v2/Users/:userId。用户变更请求先经tokenRoute验证 SCIM token再转发 Better Auth 的 SCIM 处理随后通过syncScimMutationFromResponse将结果同步进组织成员关系syncExternalIdentityFromScimResource/syncExternalIdentityFromScimUserId同步失败时返回带retry-after: 60的 503停用deactivation拦截由于未加载 better-auth 的 admin 插件PUT/PATCH请求携带active: false时由 Den 侧接管直接调用syncExternalIdentityFromScimResource完成外部身份停用并返回 204删除语义DELETE /v2/Users/:userId墓碑化组织成员仅当用户无其他活跃组织成员关系时才删除全局用户。此外registerScimAuthRoutes还屏蔽了 Better Auth 原生的原始 SCIM 管理路由/api/auth/scim/generate-token、/list-provider-connections、/get-provider-connection、/delete-provider-connection一律返回 403 并提示改用组织级 Den 路由。依赖解析认证实例、会话与请求校验README Expected dependencies 列出了该目录的三类依赖逐一说明其角色Better Auth 配置src/auth.tsauth.ts 是整个认证面的底座使用betterAuthdrizzleAdapter构建加载了organization、emailOTP、jwt、apiKey、oauthProvider、scim、sso等插件社交登录提供商GitHub / Google按环境变量条件启用auth.ts。该文件还定义了 MCP OAuth 的资源集合DEN_MCP_OAUTH_RESOURCE、DEN_MCP_RESOURCES、DEN_MCP_SCOPES等与normalizeMcpOAuthResource归一化函数是上述 OAuth 标准化的依据。同时它以RAW_BETTER_AUTH_MUTATION_DENIALS列表auth.ts拒绝通过 Better Auth 直连修改组织/SSO/团队的请求强制走 Den 自有 API。共享认证/会话中间件src/session.tssession.ts 定义了AuthContextVariablesuser/session/apiKey并支持多种凭证形态cookie 会话兼容openwork-den.session_token、__Secure-openwork-den.session_token、better-auth.session_token等 cookie 名session.tsBearer token解析Authorization: Bearer ...并解析对应会话readBearerToken/bearerSessionValueAPI key通过DEN_API_KEY_HEADER读取调用auth.api.verifyApiKey校验后解析出用户与活跃组织getSessionFromApiKey进程内 MCP principalx-den-internal-mcp-principal头由进程启动时随机生成的 32 字节密钥 HMAC 签名60 秒 TTL外部攻击者即使获得betterAuthSecret也无法伪造封闭了内部调用方冒充的信任边界。请求校验中间件src/middleware/middleware/index.ts 统一导出admin、current-user、route-access、user-organizations、organization-context、member-teams、validation模块认证路由用到的publicRoute、tokenRoute、userSessionRoute、authenticatedRoute、jsonValidator、queryValidator均来自该目录负责参数校验、会话强制与路由访问控制。未来工作方向README 给出了两条明确的演进约定可以作为继续深入该模块的开发指引浏览器认证路由保持挂在 Better Auth 之下除非有强烈理由才做包裹改写——这意味着新的浏览器端认证能力应优先以 Better Auth 插件/配置形式落地而不是在 Den 侧复制一套认证相关的自定义端点一律放本目录不要混入me/当前用户资源或org/组织资源目录以维持认证表面的单一归属与可审计性。小结ee/apps/den-api/src/routes/auth/是 OpenWork Den API 认证能力的汇聚点以 Better Auth 为内核处理标准浏览器认证以desktop-handoff三端点衔接桌面端会话以 MCP OAuth 标准化与发现端点服务 MCP 客户端以 SCIM 路由支撑企业身份供给并辅以单组织模式、密码策略、多级限流等安全控制。理解该目录的职责边界与调用链是扩展 OpenWork 认证能力、排查登录问题的起点。【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表