部署和维护 / 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 | |
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 | |
返回内容中的 issuer 必须与 OIDC_ISSUER_URL 一致。
DataFlux Func 根据公开访问基地址自动生成 OIDC 回调地址和 Web 客户端地址。使用虚拟目录部署时,公开访问基地址应包含该目录,例如 https://func.example.com/virtual;对应地址将分别生成为 https://func.example.com/virtual/api/v1/auth/oidc/callback 和 https://func.example.com/virtual/client-app/。
2.2 配置 Keycloak
相关字段可参考 Keycloak Server Administration Guide 和 Keycloak 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 已关联 profile、email 和 phone 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:
- 进入「Clients / dataflux-func / Roles」,创建名称为
dataflux-func-admin的 Role。 - 进入「Users / 用户 / Role mapping」,点击【Assign role】。
- 筛选 Client Role,选择
dataflux-funcClient 下的dataflux-func-admin并完成分配。
如需按 Group 管理成员,可以将 dataflux-func-admin Client Role 分配给 Keycloak Group,再将用户加入该 Group。
在 Client Scope 评估页面检查 Access Token,确认其中包含:
| JSON | |
|---|---|
1 2 3 4 5 6 7 | |
默认的 OIDC_ROLE_MAP 已包含 dataflux-func-admin: "admin",OIDC_ROLE_CLAIM_SOURCES 也已包含 "accessToken",因此本文示例无需再配置 OIDC_ROLE_MAP 或 OIDC_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是浏览器访问 DataFlux Func 的公开基地址,启用 OIDC 登录时必须配置;仅支持http或https,不要包含用户信息、查询参数或锚点- 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-configurationOIDC_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_CLAIM 和 OIDC_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 | |
因此,身份提供方返回 "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 会整体替换默认映射,而不是追加映射。上例同时保留了两个默认项;不再需要默认映射时可以省略。
角色映射遵循以下规则:
- 映射键按角色值精确匹配并区分大小写
- 未配置映射的角色值会保持不变;如果它本身是有效本地角色,例如
"admin"或"user",仍会直接使用 - 映射结果必须是已存在的本地角色;未映射且不是本地角色的原始值以及无效的映射结果会被忽略,重复的本地角色会去重
OIDC_ROLE_DEFAULT应直接填写本地角色,不经过OIDC_ROLE_MAP映射
2.3.3 使用其他角色 Claim
仅当身份提供方无法提供 Client Role 时,才使用 OIDC_ROLES_CLAIM 配置兜底 Claim。例如,从 Realm Role 中读取角色:
| YAML | |
|---|---|
1 | |
Claim 可以是单个值或数组。每个角色值会先按 OIDC_ROLE_MAP 映射,再匹配本地角色,因此既可以返回映射键,也可以直接返回有效本地角色。每个 Claim 来源中,映射后有效的 Client Role 优先于 OIDC_ROLES_CLAIM。
角色 Claim 默认按以下顺序读取,找到第一个包含有效角色的来源后即停止:
| YAML | |
|---|---|
1 | |
"userInfo" 仅在启用 OIDC_FETCH_USERINFO 且身份提供方支持 UserInfo Endpoint 时可用;"accessToken" 仅在 Access Token 为 JWT 时可用。
2.4 验证登录
- 打开 DataFlux Func 登录页,确认出现 OIDC 登录按钮;默认按钮文案为【使用 OpenID Connect 登录】。
- 使用未分配有效 Client Role 的新用户登录,确认其角色为
"user"。 - 使用已分配
dataflux-func-adminClient Role 的新用户登录,确认其本地角色为"admin"。 - 使用默认的
"always"策略时,移除该用户的dataflux-func-adminClient Role,退出后重新登录,确认其角色恢复为"user"。 - 如自定义了
OIDC_ROLE_MAP,分配自定义映射键对应的外部角色,重新登录并确认其本地角色符合映射结果。 - 核对用户名、姓名、邮箱和手机号。
- 验证两类用户的实际操作权限。
- 退出后确认内置管理员仍可登录。
- 全部验证通过后,再按需禁用内置登录。
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: true或OIDC_ENABLED: false会使已有 OIDC 用户的本地会话无法继续访问。
不要默认授予管理员角色
不要配置 OIDC_ROLE_DEFAULT: "admin",也不要将成员范围过大的外部 Group 或 Role 映射为 "admin"。将 Claim 映射为 "admin" 时,必须严格限制对应 Keycloak Group 或 Role 的成员。
2.6 故障排查
| 现象 | 检查项 |
|---|---|
| 登录页没有 OIDC 登录按钮 | 检查 OIDC_ENABLED: true、DISABLE_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_SOURCES、OIDC_ROLE_MAP、OIDC_ROLES_CLAIM 和 OIDC_ROLE_DEFAULT |
| Access Token 中有 Role 但未生效 | 确认 Access Token 为 JWT,且 "accessToken" 位于 OIDC_ROLE_CLAIM_SOURCES 中;同时检查更高优先级来源是否已包含有效角色、映射键是否精确匹配以及映射结果是否为有效本地角色 |
| 默认管理员角色映射未生效 | 检查是否在配置文件 config.yaml 中自定义 OIDC_ROLE_MAP 并替换了默认映射;需要时在自定义配置中补回 dff-admin 或 dataflux-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" |