跳转至

部署和维护 / OIDC 登录

本文以 Keycloak 为例,介绍如何为 DataFlux Func 配置 OIDC 登录。Keycloak 界面中的字段名称可能随版本变化,请以字段含义为准。

1. 快速配置

本节使用默认的 dataflux-func Client ID 和角色配置,快速启用基本 OIDC 登录。请先准备 DataFlux Func 公开访问基地址和 Keycloak Realm 的 Issuer 地址;创建 Client 后,还需要获取 Keycloak 生成的 Client Secret。

1.1 创建 Keycloak Client

在目标 Realm 中进入「Clients」,创建并配置 Client:

配置项 配置值
Client type OpenID Connect
Client ID dataflux-func
Client authentication On
Standard flow On
Valid redirect URIs https://func.example.com/api/v1/auth/oidc/callback
Home URL https://func.example.com/

将示例域名替换为 DataFlux Func 的实际公开访问地址。进入「Clients / dataflux-func / Credentials」,保留 Client ID and Secret 认证方式并复制 Client Secret。

1.2 配置 DataFlux Func

在配置文件 config.yaml 中配置以下内容,并替换公开访问基地址、Issuer 地址和 Client Secret:

YAML
1
2
3
4
WEB_SERVER_BASE_URL: https://func.example.com
OIDC_ENABLED       : true
OIDC_ISSUER_URL    : https://sso.example.com/realms/dataflux-func
OIDC_CLIENT_SECRET : "{Keycloak Client Secret}"

DataFlux Func 会根据 WEB_SERVER_BASE_URL 自动生成 OIDC 回调地址和 Web 客户端地址。使用虚拟目录部署时,应将虚拟目录包含在该地址中。

修改配置后,重启整个 DataFlux Func,不能只重启 Server。具体操作可参考 部署和维护 / 升级和重启

先验证 OIDC,再禁用内置登录

首次配置时保持 DISABLE_BUILTIN_SIGN_IN: false,并保留一个已登录的管理员页面。确认 OIDC 登录和角色均正常后,再按需将其改为 true

1.3 验证登录

打开 DataFlux Func 登录页,确认出现【使用 OpenID Connect 登录】按钮,并使用 Keycloak 用户完成登录。未分配有效 Client Role 的用户默认获得 "user" 角色;如需为用户授予 "admin" 角色,请继续阅读「2.2.3 配置 Client Role」。

2. 详细介绍

以下内容详细介绍示例地址、用户 Claim、角色映射与同步策略,以及验证和故障排查方法。

2.1 准备信息

本文使用以下示例信息:

项目 示例值
DataFlux Func 公开访问基地址 https://func.example.com
Keycloak 公开访问地址 https://sso.example.com
Keycloak Realm dataflux-func
Keycloak Client ID dataflux-func
OIDC Issuer https://sso.example.com/realms/dataflux-func
OIDC 回调地址 https://func.example.com/api/v1/auth/oidc/callback
DataFlux Func Web 客户端地址 https://func.example.com/client-app/

从 DataFlux Func Server 所在网络访问以下地址,确认 Keycloak 可用:

Bash
1
curl -fsS 'https://sso.example.com/realms/dataflux-func/.well-known/openid-configuration'

返回内容中的 issuer 必须与 OIDC_ISSUER_URL 一致。

DataFlux Func 根据公开访问基地址自动生成 OIDC 回调地址和 Web 客户端地址。使用虚拟目录部署时,公开访问基地址应包含该目录,例如 https://func.example.com/virtual;对应地址将分别生成为 https://func.example.com/virtual/api/v1/auth/oidc/callbackhttps://func.example.com/virtual/client-app/

2.2 配置 Keycloak

相关字段可参考 Keycloak Server Administration GuideKeycloak Protocol Mappers

2.2.1 创建 Client

在目标 Realm 中进入「Clients」,创建 Client:

配置项 配置值
Client type OpenID Connect
Client ID dataflux-func
Name DataFlux Func

保存后配置:

配置项 配置值
Client authentication On
Authorization Off
Standard flow On
Direct access grants Off
Implicit flow Off
Service accounts roles Off
Valid redirect URIs https://func.example.com/api/v1/auth/oidc/callback
Home URL https://func.example.com/

进入「Clients / dataflux-func / Credentials」,保留 Client ID and Secret 认证方式并复制 Client Secret。

妥善保管 Client Secret

不要将真实 Client Secret 写入公开文档、日志或代码仓库,也不要在浏览器端使用。

2.2.2 配置用户 Claim

确认 Client 已关联 profileemailphone Client Scope。DataFlux Func 默认使用以下 Claim:

用户字段 Claim
用户名 preferred_username
姓名 name
邮箱 email
手机号 phone_number

2.2.3 配置 Client Role

DataFlux Func 优先从 resource_access.<OIDC_CLIENT_ID>.roles 读取 Client Role。收到的角色值会先按 OIDC_ROLE_MAP 映射,再匹配本地角色。Role 名称和映射键均区分大小写,本文只介绍本地 "admin""user" 两种角色。

未匹配到有效本地角色时,用户默认获得 "user" 角色,因此普通用户无需额外配置。默认的 OIDC_ROLE_MAP 会将 "dataflux-func-admin" 映射为本地 "admin" 角色。为管理员配置该 Client Role:

  1. 进入「Clients / dataflux-func / Roles」,创建名称为 dataflux-func-admin 的 Role。
  2. 进入「Users / 用户 / Role mapping」,点击【Assign role】。
  3. 筛选 Client Role,选择 dataflux-func Client 下的 dataflux-func-admin 并完成分配。

如需按 Group 管理成员,可以将 dataflux-func-admin Client Role 分配给 Keycloak Group,再将用户加入该 Group。

在 Client Scope 评估页面检查 Access Token,确认其中包含:

JSON
1
2
3
4
5
6
7
{
  "resource_access": {
    "dataflux-func": {
      "roles": [ "dataflux-func-admin" ]
    }
  }
}

默认的 OIDC_ROLE_MAP 已包含 dataflux-func-admin: "admin"OIDC_ROLE_CLAIM_SOURCES 也已包含 "accessToken",因此本文示例无需再配置 OIDC_ROLE_MAPOIDC_ROLES_CLAIM

严格控制管理员 Client Role

dataflux-func-admin Client Role 会映射为 DataFlux Func 的 "admin" 角色。不要将其设为默认 Role,并应严格限制 Role 管理权限和成员。

2.3 配置 DataFlux Func

标准容器部署时,将以下配置写入容器内的 /data/user-config.yaml,对应的宿主机默认位置为 {安装目录}/data/user-config.yaml。配置文件位置可参考 部署和维护 / 数据保存位置

在配置文件 config.yaml 中配置以下内容,并替换示例地址、Realm 和 Client Secret:

YAML
1
2
3
4
WEB_SERVER_BASE_URL: https://func.example.com
OIDC_ENABLED       : true
OIDC_ISSUER_URL    : https://sso.example.com/realms/dataflux-func
OIDC_CLIENT_SECRET : "{Keycloak Client Secret}"

配置时注意:

  • WEB_SERVER_BASE_URL 是浏览器访问 DataFlux Func 的公开基地址,启用 OIDC 登录时必须配置;仅支持 httphttps,不要包含用户信息、查询参数或锚点
  • DataFlux Func 会移除 WEB_SERVER_BASE_URL 末尾的斜杠,再分别追加 /api/v1/auth/oidc/callback/client-app/;生成的回调地址必须与 Keycloak 的 Valid redirect URIs 完全一致
  • 使用虚拟目录部署时,必须将虚拟目录包含在 WEB_SERVER_BASE_URL
  • OIDC_ISSUER_URL 填写 Issuer 地址,不要追加 /.well-known/openid-configuration
  • OIDC_CLIENT_ID 默认是 "dataflux-func",与本文创建的 Keycloak Client 一致

如需修改显示名称、Claim、Scope、角色来源、角色映射、同步策略或地址,参考文末附录:完整配置项

修改配置后,重启整个 DataFlux Func,不能只重启 Server。具体操作可参考 部署和维护 / 升级和重启

先验证 OIDC,再禁用内置登录

首次配置时保持 DISABLE_BUILTIN_SIGN_IN: false,并保留一个已登录的管理员页面。确认 OIDC 登录和角色均正常后,再按需将其改为 true

2.3.1 选择角色同步策略

OIDC_ROLE_SYNC_POLICY 控制 OIDC 角色何时写入 DataFlux Func:

配置值 行为
"always" 默认值。创建用户及以后每次登录时同步角色;映射后没有有效外部角色时同步为 OIDC_ROLE_DEFAULT
"initial" 仅在首次创建本地用户时写入角色;以后登录保留 DataFlux Func 中的既有角色
"never" 忽略 Client Role、OIDC_ROLES_CLAIMOIDC_ROLE_MAP;创建用户及以后每次登录时均使用 OIDC_ROLE_DEFAULT

手工角色可能被覆盖

使用默认的 "always" 或使用 "never" 时,用户每次 OIDC 登录都会同步角色。不要依赖在 DataFlux Func 中对 OIDC 用户进行的手工角色调整;如需保留手工调整,应配置 OIDC_ROLE_SYNC_POLICY: "initial"

2.3.2 配置角色映射

OIDC_ROLE_MAP 以身份提供方返回的角色值为键,以 DataFlux Func 本地角色为值,同时作用于 Client Role 和 OIDC_ROLES_CLAIM。DataFlux Func 在配置文件 config.yaml 中配置了以下默认映射:

YAML
1
2
3
OIDC_ROLE_MAP:
  dff-admin          : "admin"
  dataflux-func-admin: "admin"

因此,身份提供方返回 "dff-admin""dataflux-func-admin" 时,用户均获得本地 "admin" 角色。本文的 Keycloak 示例使用 "dataflux-func-admin",无需额外配置。

如身份提供方使用 "func-administrators""func-users",可以在配置文件 config.yaml 中配置:

YAML
1
2
3
4
5
OIDC_ROLE_MAP:
  dff-admin          : "admin"
  dataflux-func-admin: "admin"
  func-administrators: "admin"
  func-users         : "user"

自定义 OIDC_ROLE_MAP 会整体替换默认映射,而不是追加映射。上例同时保留了两个默认项;不再需要默认映射时可以省略。

角色映射遵循以下规则:

  • 映射键按角色值精确匹配并区分大小写
  • 未配置映射的角色值会保持不变;如果它本身是有效本地角色,例如 "admin""user",仍会直接使用
  • 映射结果必须是已存在的本地角色;未映射且不是本地角色的原始值以及无效的映射结果会被忽略,重复的本地角色会去重
  • OIDC_ROLE_DEFAULT 应直接填写本地角色,不经过 OIDC_ROLE_MAP 映射

2.3.3 使用其他角色 Claim

仅当身份提供方无法提供 Client Role 时,才使用 OIDC_ROLES_CLAIM 配置兜底 Claim。例如,从 Realm Role 中读取角色:

YAML
1
OIDC_ROLES_CLAIM: "realm_access.roles"

Claim 可以是单个值或数组。每个角色值会先按 OIDC_ROLE_MAP 映射,再匹配本地角色,因此既可以返回映射键,也可以直接返回有效本地角色。每个 Claim 来源中,映射后有效的 Client Role 优先于 OIDC_ROLES_CLAIM

角色 Claim 默认按以下顺序读取,找到第一个包含有效角色的来源后即停止:

YAML
1
OIDC_ROLE_CLAIM_SOURCES: [ "idToken", "userInfo", "accessToken" ]

"userInfo" 仅在启用 OIDC_FETCH_USERINFO 且身份提供方支持 UserInfo Endpoint 时可用;"accessToken" 仅在 Access Token 为 JWT 时可用。

2.4 验证登录

  1. 打开 DataFlux Func 登录页,确认出现 OIDC 登录按钮;默认按钮文案为【使用 OpenID Connect 登录】。
  2. 使用未分配有效 Client Role 的新用户登录,确认其角色为 "user"
  3. 使用已分配 dataflux-func-admin Client Role 的新用户登录,确认其本地角色为 "admin"
  4. 使用默认的 "always" 策略时,移除该用户的 dataflux-func-admin Client Role,退出后重新登录,确认其角色恢复为 "user"
  5. 如自定义了 OIDC_ROLE_MAP,分配自定义映射键对应的外部角色,重新登录并确认其本地角色符合映射结果。
  6. 核对用户名、姓名、邮箱和手机号。
  7. 验证两类用户的实际操作权限。
  8. 退出后确认内置管理员仍可登录。
  9. 全部验证通过后,再按需禁用内置登录。

2.5 注意事项

  • 默认的 "always" 策略会在每次登录时同步角色。Keycloak Role 发生变化后,用户需要退出并重新登录;"initial" 策略下则需在 DataFlux Func 中手工调整既有用户角色。
  • 角色按 OIDC_ROLE_CLAIM_SOURCES 的顺序读取,不会合并不同来源;每个来源中先映射并筛选 resource_access.<OIDC_CLIENT_ID>.roles,没有有效 Client Role 时再映射并筛选 OIDC_ROLES_CLAIM
  • OIDC_ROLE_MAP 的映射键和结果均区分大小写;在配置文件 config.yaml 中自定义该配置会替换整个默认映射。
  • OIDC_ROLES_CLAIM 可以读取单个值、数组或点号分隔的嵌套路径。
  • OIDC 用户名创建后不会更新;姓名、邮箱和手机号会在后续登录时更新。OIDC 用户应在 Keycloak 中修改个人资料。
  • DataFlux Func 退出登录不会结束 Keycloak SSO 会话。默认的 { prompt: "login" } 会要求 Keycloak 重新认证;配置为 {} 后,再次登录可能直接复用 Keycloak 会话。
  • 修改 WEB_SERVER_BASE_URL 后,需要同步更新身份提供方登记的回调地址;该配置中的虚拟目录也会用于登录完成后的 Web 客户端地址。
  • DISABLE_SIGN_IN: trueOIDC_ENABLED: false 会使已有 OIDC 用户的本地会话无法继续访问。

不要默认授予管理员角色

不要配置 OIDC_ROLE_DEFAULT: "admin",也不要将成员范围过大的外部 Group 或 Role 映射为 "admin"。将 Claim 映射为 "admin" 时,必须严格限制对应 Keycloak Group 或 Role 的成员。

2.6 故障排查

现象 检查项
登录页没有 OIDC 登录按钮 检查 OIDC_ENABLED: trueDISABLE_SIGN_IN: false,并确认已重启整个 DataFlux Func
点击登录后报错 检查 WEB_SERVER_BASE_URL、Keycloak 地址、TLS 证书、DNS、Client ID、Client Secret 和客户端认证方式
Keycloak 提示回调地址无效 对比 Valid redirect URIs 与 WEB_SERVER_BASE_URL/api/v1/auth/oidc/callback 后的完整地址,检查协议、域名、端口、虚拟目录和末尾斜杠
回调后提示状态无效 使用发起登录的同一浏览器完成操作,并检查 Cookie、共享 Redis、各 Server 节点的 SECRET 和 10 分钟登录时限
登录后跳转到错误的客户端地址 检查 WEB_SERVER_BASE_URL 是否为浏览器实际访问的公开基地址,以及其中的虚拟目录是否正确;客户端地址会自动生成为该基地址加 /client-app/
用户资料为空 检查 OIDC_SCOPES、Client Scope、用户资料和对应 Claim
新用户角色不正确 检查 resource_access.<OIDC_CLIENT_ID>.roles、Role 名称大小写、OIDC_ROLE_CLAIM_SOURCESOIDC_ROLE_MAPOIDC_ROLES_CLAIMOIDC_ROLE_DEFAULT
Access Token 中有 Role 但未生效 确认 Access Token 为 JWT,且 "accessToken" 位于 OIDC_ROLE_CLAIM_SOURCES 中;同时检查更高优先级来源是否已包含有效角色、映射键是否精确匹配以及映射结果是否为有效本地角色
默认管理员角色映射未生效 检查是否在配置文件 config.yaml 中自定义 OIDC_ROLE_MAP 并替换了默认映射;需要时在自定义配置中补回 dff-admindataflux-func-admin
既有用户角色未同步 检查 OIDC_ROLE_SYNC_POLICY;配置为 "initial" 时应在 DataFlux Func 中手工调整既有用户角色
退出后再次登录未要求认证 检查 OIDC_AUTHORIZATION_PARAMS_MAP 是否被覆盖为 {},以及 Keycloak 对 prompt: "login" 的处理

附录:完整配置项

附录按本文采用的 OIDC 配置方式列出完整配置项。

配置项 默认值 示例 说明
WEB_SERVER_BASE_URL "" https://func.example.com 浏览器访问 DataFlux Func 的公开基地址;OIDC 登录必填,程序据此自动生成回调地址和 Web 客户端地址
OIDC_ENABLED false true 配置为 true 以启用 OIDC 登录
OIDC_ISSUER_URL "" https://sso.example.com/realms/dataflux-func 身份提供方的 Issuer 地址,不包含 /.well-known/openid-configuration
OIDC_CLIENT_SECRET "" Client Secret;使用默认 Token Endpoint 认证方式时必填
配置项 默认值 说明
DISABLE_SIGN_IN false 是否全局禁用内置、集成和 OIDC 登录;启用 OIDC 时必须保持 false
DISABLE_BUILTIN_SIGN_IN false 是否禁用内置用户名密码登录;仅在 OIDC 验证完成后按需配置为 true
OIDC_DISPLAY_NAME "OpenID Connect" OIDC 登录按钮中显示的身份提供方名称;可按需自定义
OIDC_CLIENT_ID "dataflux-func" 本文 Keycloak Client 使用默认值;身份提供方分配的 Client ID 不同时需配置为对应值
OIDC_TOKEN_ENDPOINT_AUTH_METHOD "client_secret_basic" Token Endpoint 认证方式;仅在身份提供方要求 "client_secret_post""none" 时配置
OIDC_SCOPES [ "openid", "profile", "email", "phone" ] 请求的 Scope;未包含 "openid" 时会自动添加
OIDC_AUTHORIZATION_PARAMS_MAP { prompt: "login" } 附加到认证请求的参数;复用身份提供方已有会话时配置为 {}
OIDC_FETCH_USERINFO true 是否请求 UserInfo Endpoint 获取用户 Claim
OIDC_USERNAME_CLAIM "preferred_username" 用户名 Claim 路径;身份提供方使用其他 Claim 时需配置为对应路径
OIDC_NAME_CLAIM "name" 姓名 Claim 路径;身份提供方使用其他 Claim 时需配置为对应路径
OIDC_EMAIL_CLAIM "email" 邮箱 Claim 路径;身份提供方使用其他 Claim 时需配置为对应路径
OIDC_MOBILE_CLAIM "phone_number" 手机号 Claim 路径;身份提供方使用其他 Claim 时需配置为对应路径
OIDC_ROLE_CLAIM_SOURCES [ "idToken", "userInfo", "accessToken" ] 读取角色 Claim 的来源及优先级;可用值为 "idToken""userInfo""accessToken"
OIDC_ROLES_CLAIM "" Client Role 经映射后没有有效角色时使用的兜底 Claim 路径;适用于身份提供方无法提供 Client Role 的场景
OIDC_ROLE_MAP { dff-admin: "admin", dataflux-func-admin: "admin" } 将 Client Role 和兜底 Claim 中的外部角色值映射为本地角色;自定义配置会整体替换默认映射
OIDC_ROLE_DEFAULT "user" 映射后没有有效外部角色时使用的本地角色,不经过 OIDC_ROLE_MAP
OIDC_ROLE_SYNC_POLICY "always" 角色同步策略;可改为 "initial""never"