理解 OIDC 协议,学会将任意应用接入 Keycloak 单点登录
环境: auth.huojin.com | Realm: huojinKeycloak 是一个开源的身份和访问管理(IAM)系统,它帮你搞定三件事:
1. 认证(Authentication) — 确认用户是谁(用户名密码 / LDAP / 社交登录)
2. 授权(Authorization) — 控制用户能干什么(角色、权限)
3. 单点登录(SSO) — 登录一次,所有接入的应用都能用
架构示意:Keycloak 作为认证中心,各应用通过 OIDC 协议对接
| 概念 | 说明 | 类比 |
|---|---|---|
| Realm | Keycloak 中的独立租户,一个公司/产品一个 Realm | 一栋大楼 |
| Client | 每个接入的应用是一个 Client | 大楼里的一个房间 |
| User | Realm 中的用户,可跨 Client 登录 | 持门禁卡的员工 |
| Client Secret | Client 的密钥,用于后端验证身份 | 房间钥匙 |
| Redirect URI | 登录成功后的回调地址,必须在 Client 中预先配置 | 回程路径 |
| Access Token | 短期令牌(通常 5 分钟),携带用户权限信息 | 临时通行证 |
| ID Token | 包含用户身份信息(JWT 格式) | 身份证 |
| Refresh Token | 长期令牌,用于自动续期 Access Token | 续期凭证 |
这是最核心的 Authorization Code Flow(授权码流程),绝大多数 Web 应用都使用这个:
| 步骤 | HTTP 动作 | 关键参数 | 安全机制 |
|---|---|---|---|
| 1-2 发起授权 | GET 浏览器重定向 | client_id=jumpserver redirect_uri=... response_type=code scope=openid state=随机串 code_challenge=S256哈希 |
state 防 CSRF PKCE 防截持 |
| 3-4 登录+回调 | POST 登录表单 GET 回调 | code=一次性授权码 session_state=... |
code 只能用一次 5分钟内过期 |
| 5 换 Token | POST 后端请求 | grant_type=authorization_code client_id + client_secret code + code_verifier redirect_uri |
仅后端可见 Secret 不暴露 |
| 6 验签入站 | 后端验证 | 用 JWKS 公钥验证签名 检查 exp / aud / iss |
非对称加密 防伪造 Token |
地址:https://auth.huojin.com/admin
账号:admin
左侧菜单 Clients → Create client:
| 字段 | 示例值 | 说明 |
|---|---|---|
| Client ID | jumpserver | 应用唯一标识,全小写 |
| Name | JumpServer 堡垒机 | 显示名称(可选) |
| Client Protocol | openid-connect | 固定选这个 |
| Always display | ON | 登录页显示此应用 |
创建后进入 Settings 标签页:
| 字段 | 值 |
|---|---|
| Client authentication | On(需要 Secret) |
| Authorization | On(启用授权) |
| Standard flow | On ✅ 标准授权码流程 |
| Direct access grants | Off ❌ 禁止跳过浏览器直接登录 |
| Implicit flow | Off ❌ 仅 SPA 才需要 |
| Valid redirect URIs | https://jumpserver.miaoma.com/* |
| Valid post logout redirect URIs | https://jumpserver.miaoma.com/ |
| Web origins | +(允许所有配置的 Redirect URI) |
/* 通配符,因为 Keycloak 会往 callback URL 后追加参数如 ?state=xxx&code=yyy。不行也得写完整的 callback 路径。
进入 Credentials 标签页 → 复制 Client Secret,这是应用后端需要的密钥。
大部分现代应用都原生支持 OIDC,只需配置 4 个核心参数:
| 参数 | Keycloak 中的值 |
|---|---|
| Provider / Issuer URL | https://auth.huojin.com/realms/huojin |
| Client ID | 你在 Keycloak 创建的 Client ID |
| Client Secret | 从 Credentials 标签页获取 |
| Scopes | openid profile email |
填写后,应用会自动从以下地址发现所有端点:
https://auth.huojin.com/realms/huojin/.well-known/openid-configuration
这个 JSON 文件包含了 authorization_endpoint、token_endpoint、userinfo_endpoint 等所有必要地址,应用会自动解析。
| 应用 | 支持方式 | 配置位置 | 备注 |
|---|---|---|---|
| JumpServer | 原生 OIDC | 系统设置 → 认证 → OIDC | 先绑定MFA才能看到设置 |
| GitLab | 原生 OmniAuth | gitlab.rb 配置文件 |
支持自动创建用户 |
| Grafana | 原生 OIDC | grafana.ini |
支持角色映射 |
| Nexus | 仅 SAML | 需 Keycloak SAML Client | 或用 OIDC 反向代理插件 |
| Vaultwarden | 不支持 SSO | — | 仅本地账号 |
| NPM | 不支持 SSO | — | 可通过 Access List 限制 IP |
配置完成后,按以下步骤逐项验证:
| # | 验证项 | 预期结果 |
|---|---|---|
| 1 | 打开应用登录页 | 出现 "OIDC 登录" / "通过 Keycloak 登录" 按钮 |
| 2 | 点击 OIDC 按钮 | 跳转到 auth.huojin.com 登录页 |
| 3 | 输入 Keycloak 账号密码 | 登录成功,跳回应用 |
| 4 | 检查用户创建 | 应用后台出现新用户,用户名与 Keycloak 一致 |
| 5 | 退出后再次登录 | 如 Keycloak 会话未过期,免密直接进入 |
| 6 | Keycloak 注销 | 所有应用的 Keycloak 会话同时失效 |
| 项目 | 值 |
|---|---|
| Keycloak 地址 | https://auth.huojin.com |
| 管理后台 | https://auth.huojin.com/admin |
| Realm | huojin |
| 已创建 Client | jumpserver / gitlab / nexus |
| 接入进度 | Client 已创建,应用侧 ⬜ 待配置 |