Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

统一 IdP 抽象(OIDC + OAuth2)

把 Inbound OIDC 的 tenant_oidc_providers 扩展成「外部身份提供方」统一抽象,让租户在 UI 上自助配置任意登录源——既支持标准 OIDC IdP(Keycloak/Azure/Google),也支持 OAuth2 提供方(Gitee/GitHub/微信/飞书等非标准 OIDC),并按租户停用。 定稿 2026-07-10。前置:Inbound OIDC(docs/TENANT_PHASE5_INBOUND_OIDC.md)、Gitee 硬编码(commit 1a058c7)。


0. 为什么

当前 auth 有两套登录入口:

  • 硬编码 handler:GitHub、Gitee(每家一个 handler + 全局 client_id/secret,所有租户共享,租户无法停用/自定义)。
  • 配置化 IdP:Inbound OIDC(tenant_oidc_providers,每租户配企业 IdP,可停用)——但只支持标准 OIDC(依赖 discovery + id_token + 标准 userinfo),接不上 Gitee/微信等 OAuth2 平台。

目标是统一成一套配置:租户管理员在 UI 配一个 IdP(选类型 OIDC/OAuth2),填对应参数,就能接入任意登录源,并能停用。这是 IDaaS 的核心能力(Auth0/Casbin 的 social connections 都这么设计)。


1. 数据模型扩展(tenant_oidc_providers 加字段)

ALTER TABLE tenant_oidc_providers ADD COLUMN provider_type VARCHAR(10) DEFAULT 'oidc';  -- 'oidc' | 'oauth2'
-- OAuth2 手填 endpoints(OIDC 用 discovery,这几列留空)
ALTER TABLE tenant_oidc_providers ADD COLUMN authorize_url TEXT;
ALTER TABLE tenant_oidc_providers ADD COLUMN token_url TEXT;
ALTER TABLE tenant_oidc_providers ADD COLUMN userinfo_url TEXT;
-- OAuth2 userinfo 字段映射(OIDC 用标准 sub/email,这几列留空走默认)
ALTER TABLE tenant_oidc_providers ADD COLUMN field_id VARCHAR(50) DEFAULT 'id';
ALTER TABLE tenant_oidc_providers ADD COLUMN field_username VARCHAR(50) DEFAULT 'login';
ALTER TABLE tenant_oidc_providers ADD COLUMN field_email VARCHAR(50) DEFAULT 'email';
ALTER TABLE tenant_oidc_providers ADD COLUMN field_name VARCHAR(50) DEFAULT 'name';
ALTER TABLE tenant_oidc_providers ADD COLUMN field_avatar VARCHAR(50) DEFAULT 'avatar_url';
-- OAuth2 token 传递与编码
ALTER TABLE tenant_oidc_providers ADD COLUMN userinfo_token_in VARCHAR(10) DEFAULT 'query';  -- 'query'(?access_token=) | 'header'(Authorization: Bearer)
ALTER TABLE tenant_oidc_providers ADD COLUMN token_content_type VARCHAR(10) DEFAULT 'form';  -- 'form'(x-www-form-urlencoded) | 'json'

现有 IdP 配置迁移:provider_type='oidc'(默认),新字段空走 OIDC discovery,零破坏。


2. RP 逻辑泛化(src/sso.rs

start(GET /api/auth/sso/:provider_id/start

provider_type 分支:

  • oidcdiscover(issuer) 拿 authorization_endpoint + 生成 PKCE(code_challenge)+ state 存 Redis → 302。(现有逻辑)
  • oauth2:用 authorize_url(手填)+ state 存 Redis(不生成 PKCE,多数 OAuth2 如 Gitee/GitHub 不要求;若某些平台要,可后续加 use_pkce 开关)→ 302。

callback(GET /api/auth/sso/callback?code=&state=

  • 换 token:
    • oidcPOST discovery.token_endpoint + code_verifier(PKCE)→ {access_token, id_token}
    • oauth2POST token_url,body 按 token_content_type(form/json),含 grant_type=authorization_code, code, client_id, redirect_uri, client_secret(无 code_verifier)→ {access_token}
  • userinfo:
    • oidcGET discovery.userinfo_endpoint + Authorization: Bearer → 标准 {sub, email, name}
    • oauth2GET userinfo_url,token 按 userinfo_token_in(query ?access_token= 或 header)→ 按 field_* 映射取 {id, username, email, name, avatar}
  • 用户映射(统一):oauth_provider = format!("idp:{}", provider_id)oauth_id = mapped_id

公开端点(GET /api/auth/sso/providers?tenant_id=

[{id, name, provider_type}](加 provider_type 供登录页按类型显示图标/文案;不返敏感)。


3. 字段映射示例(覆盖主流 OAuth2 平台)

平台authorize_urltoken_urluserinfo_urlfield_idfield_usernameuserinfo_token_intoken_content_type
Giteehttps://gitee.com/oauth/authorizehttps://gitee.com/oauth/tokenhttps://gitee.com/api/v5/useridloginqueryform
GitHubhttps://github.com/login/oauth/authorizehttps://github.com/login/oauth/access_tokenhttps://api.github.com/useridloginheaderjson
通用 OAuth2各自填各自填各自填配置配置配置配置

租户管理员在 UI 填这些 → 接入对应平台。


4. UI(admin-ui/src/sso_providers.vue

  • 表单加「类型」选择:OIDC / OAuth2。
  • OIDC 显示:issuer(discovery 用)。
  • OAuth2 显示:authorize_url / token_url / userinfo_url + 字段映射(field_id/username/email/name/avatar)+ userinfo_token_in(query/header)+ token_content_type(form/json)+ scope。
  • 通用:name / client_id / client_secret / is_active(停用开关)。
  • 预置模板(可选 UX 加分):点「Gitee 模板」自动填 Gitee 的 URL/字段映射,租户只补 client_id/secret。

5. 硬编码 GitHub/Gitee 已退役(2026-07)

  • 硬编码 github_oauth_* / gitee_oauth_* handler 与 .envGITHUB_* / GITEE_* 配置已移除
  • 全部统一到配置化 IdP:社交登录(GitHub/Gitee)和企业 SSO(OIDC)都走 tenant_oidc_providers 表 + /api/auth/sso/* 路径。
  • 功能平移:db.rs 启动迁移在 default 租户下自动创建 GitHub OAuth2 IdP(读 .envGITHUB_CLIENT_ID/SECRET,幂等判重);Gitee 早已预置(id=1)。
  • 历史 oauth_provider 值:硬编码 'github'/'gitee'(遗留账号)vs 配置 'idp:{id}'(新登录)。两套不冲突,老账号原值不变。

6. 工作量(1 人估)

子项工作量
表扩展 + 迁移 + 模型字段~1 天
RP 逻辑泛化(start/callback 按 type 分支 + 字段映射 + token 传递)~3 天
公开端点 + UI(sso_providers.vue type 选择 + 条件字段 + 模板)~2 天
测试(oidc 路径不回归 + oauth2 用 Gitee 实测)~1 天
合计~1 周

7. 边界(本阶段不做)

  • ❌ 硬编码 GitHub/Gitee 迁移到 IdP 配置(保留兼容,迁移影响现有用户 oauth_provider 值)。
  • ❌ 微信/飞书自有协议适配(它们连标准 OAuth2 都不算,有 openid/app_id 等特有字段,要再单独适配;本阶段只支持「标准 OAuth2 + 字段映射」能覆盖的平台如 Gitee/GitHub)。
  • ❌ SAML(仍等大客户要再做)。
  • ❌ 租户级硬编码停用(硬编码是平台预置全局,租户不能停;租户只管自己配的 IdP)。