场景

你需要让用户用已有的 Google / GitHub / Apple / Microsoft 账号登录你的应用,而不是注册新账号。Keycloak 作为 IAM 中台统一对接这些社交身份提供商(Social Identity Provider),应用只需要对接 Keycloak 一个 OIDC 端点,不用关心上游 IdP 的差异。

适用场景

  • SaaS 产品需要降低注册门槛,允许用户用已有社交账号一键登录
  • 企业内部应用需要同时支持 AD 账号(SAML/LDAP)和外部合作伙伴的 Google/GitHub 账号
  • 开发者工具类产品,目标用户习惯用 GitHub 登录
  • 移动端 App 需要 Apple Sign In(App Store 审核要求)

不适用场景

  • 只有企业内部 AD/LDAP 用户,不需要外部社交账号——直接用 Keycloak LDAP / AD 用户联邦
  • 需要对接多个企业 IdP(如合作伙伴的 Okta/Azure AD)——这是 身份联邦 的场景
  • 只需要一种社交登录且前端直接对接(不走 Keycloak 代理)——直接用相应 SDK 即可

核心原理

Keycloak 的身份代理(Identity Broker)在用户和外部 IdP 之间充当中间层:

用户 ──→ 应用 ──→ Keycloak ──→ Google/GitHub/Apple/Microsoft
                  │
                  ├── 统一的 OIDC/SAML 接口
                  ├── 属性映射和转换
                  ├── JIT 用户自动创建
                  └── 账户关联(多个社交账号绑定同一用户)

通用步骤

无论对接哪个社交 IdP,配置流程都是三步:

  1. 在目标平台注册应用,获取 Client ID 和 Client Secret
  2. 在 Keycloak 中添加 Identity Provider,填入凭据
  3. 配置回调 URI 和属性映射,验证登录流程

各平台配置详解

Google 登录

第一步:Google Cloud Console 创建 OAuth 2.0 凭据

  1. 打开 Google Cloud Console
  2. 创建项目 → APIs & Services → Credentials
  3. 配置 OAuth consent screen(选 External,添加测试用户或发布)
  4. 创建 OAuth 2.0 Client ID,类型选 “Web application”
  5. Authorized redirect URIs 填入:
    https://auth.example.com/realms/myrealm/broker/google/endpoint
  6. 记录 Client ID 和 Client Secret

第二步:Keycloak 配置

  1. Realm Settings → Identity Providers → Add provider → Google
  2. 填入 Client ID 和 Client Secret
  3. 保持默认的 Scopes:openid profile email
  4. 保存

第三步:验证

访问 https://auth.example.com/realms/myrealm/account,点击 Google 登录按钮。首次登录会自动创建 Keycloak 用户(前提是 First Login Flow 配置允许)。

Google 特有的坑:

症状原因解决
redirect_uri_mismatchGoogle Console 中配置的回调 URI 与 Keycloak 实际使用的不同确认 URI 格式为 https://<host>/realms/<realm>/broker/google/endpoint,注意末尾没有 /
刷新 Token 失效Google 的 refresh token 在用户改密后会吊销给用户提示"需要重新授权",不要假定 refresh token 永久有效
access_denied 且无详细错误OAuth consent screen 未发布或测试用户未添加在 Google Console 的 OAuth consent screen 中把测试邮箱加入 Test users

GitHub 登录

第一步:GitHub 创建 OAuth App

  1. GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
  2. Authorization callback URL 填入:
    https://auth.example.com/realms/myrealm/broker/github/endpoint
  3. 记录 Client ID,生成 Client Secret

第二步:Keycloak 配置

  1. Identity Providers → Add provider → GitHub
  2. 填入 Client ID 和 Client Secret
  3. 保存

GitHub 特有的坑:

症状原因解决
拿不到用户的私有邮箱GitHub 用户可能设置了 “Keep my email addresses private”添加 scope user:email,Keycloak 默认已包含
redirect_uri_mismatchGitHub 的 callback URL 配置错误GitHub OAuth App 的回调地址必须和 Keycloak 的 redirect uri 完全一致

Apple 登录

Apple Sign In 与普通 OAuth 2.0 不同——它使用私钥签名 client_secret(JWT 格式),不用静态 secret。

第一步:Apple Developer 配置

  1. Apple Developer → Certificates, Identifiers & Profiles
  2. 注册一个 Services ID(作为 client_id)并启用 Sign in with Apple
  3. 注册一个 Private Key,下载 .p8 文件
  4. 记录 Team ID、Key ID、Services ID

第二步:Keycloak 配置

  1. Identity Providers → Add provider → Apple
  2. 填入:
    • Client ID:Services ID(如 com.example.auth
    • Key ID:上一步的 Key ID
    • Team ID:Apple Developer 的 Team ID
    • Private Key.p8 文件内容(完整 PEM 格式,包含 -----BEGIN PRIVATE KEY----- 头尾)
  3. Keycloak 会自动生成签名的 client_secret JWT
  4. 保存

第三步:Return URL 验证

Apple 的回调 URL 是 Keycloak 自动构造的:

https://auth.example.com/realms/myrealm/broker/apple/endpoint

在 Apple Developer 的 Services ID 配置中,Web Authentication Return URLs 必须填入此地址。

Apple 特有的坑:

症状原因解决
invalid_clientclient_secret JWT 签名错误检查 Key ID、Team ID、Private Key 是否正确;Keycloak 日志会输出 JWT 生成详情
只返回用户名,没有邮箱Apple 的隐私保护——用户选择了 “Hide My Email”使用 Apple 返回的 relay email(@privaterelay.appleid.com)作为用户标识
首次登录后再登录邮箱变了Apple 的 private relay email 每次可能不同(取决于 App 是否在同一个 team 下)sub claim 而非 email 作为用户唯一标识

Microsoft Entra ID(Azure AD)登录

Microsoft 支持两种模式:多租户(任何 Microsoft 账号)和单租户(仅你的组织)。Keycloak 内置的 Microsoft provider 使用 OIDC 协议对接 v2.0 端点。

第一步:Azure Portal 注册应用

  1. Azure Portal → Microsoft Entra ID → App registrations → New registration
  2. 支持的账户类型:选 “Accounts in any organizational directory and personal Microsoft accounts”(多租户)
  3. Redirect URI 类型选 “Web”,填入:
    https://auth.example.com/realms/myrealm/broker/microsoft/endpoint
  4. 注册后记录 Application (client) ID
  5. Certificates & secrets → New client secret → 记录 secret 值

第二步:Keycloak 配置

  1. Identity Providers → Add provider → Microsoft
  2. 填入 Client ID 和 Client Secret
  3. 如果要限定只允许特定租户,在 “Default Scopes” 保留默认或添加租户限定参数
  4. 保存

第三步:可选——限定租户

如果需要只允许特定组织的 Microsoft 账号登录,在 Keycloak 的 Microsoft IdP 配置中添加 Mapper:

Mapper Type: Hardcoded role
设置特定角色要求

或通过 Tenant ID 限定:在 provider 的 Authorization URL 中追加 ?tenant=<tenant-id>(需要自定义 provider URL)。

Microsoft 特有的坑:

症状原因解决
AADSTS50011: The reply URL does not matchAzure 中的 redirect URI 和 Keycloak 的不一致Azure Portal 中 App Registration 的 Redirect URI 必须是 https://<host>/realms/<realm>/broker/microsoft/endpoint
用户登录后 keycloak 报 identity provider not linked已存在同邮箱的本地用户,但未关联 Microsoft IdP使用 Account Linking(账户关联)或先删除本地用户
AADSTS9002325: Proof Key for Code Exchange is requiredAzure AD 在特定配置下强制 PKCE,但 Keycloak 默认未使用检查 Keycloak 26.x 版本,>26.0 默认启用 PKCE;如果不行,升级到最新版

JIT Provisioning 与属性映射

社交登录的默认行为是 JIT(Just-In-Time)用户自动创建:首次登录时 Keycloak 自动创建本地用户。

常用属性 Mapper(Google 为例)

进入 Identity Provider → Mappers → Add mapper:

Mapper 类型用途配置示例
Attribute Importer将 IdP 返回的属性写入用户 profileClaim: email → User Attribute: email
Username Template Importer自定义用户名生成规则Template: ${CLAIM.preferred_username}${CLAIM.email}
Hardcoded Role通过此社交 IdP 登录的用户自动获得指定角色Role: social-user

用户名冲突处理:

如果本地已存在同名用户(如 [email protected] 既注册了本地账号又用 Google 登录),Keycloak 26.x 默认行为是拒绝并提示"用户已存在"。可通过以下方式解决:

  1. Username Template Importer:用 idp_alias + email 作为用户名,如 [email protected]
  2. Account Linking:让用户先登录已有账号,再在账户设置中关联社交 IdP

验证清单

配置完成后,逐项验证:

  • 访问 https://<keycloak>/realms/<realm>/account,能看到社交登录按钮
  • 点击按钮跳转到对应平台(Google/GitHub/Apple/Microsoft)的授权页
  • 授权后回调到 Keycloak,用户自动创建或登录
  • 检查 Keycloak Users 列表,确认新用户已创建且属性正确
  • 用同一社交账号再次登录,确认是登录而非重复创建
  • 检查 https://<keycloak>/realms/<realm>/account 中的 “Linked Accounts” 区域,确认社交账号已关联

回滚方式

社交登录配置不涉及数据库结构变更,回滚简单:

  1. 进入 Identity Providers → 找到目标 provider → 点 disable(不删除,保留配置)
  2. 用户界面上的社交登录按钮立即消失
  3. 已通过该社交 IdP 创建的用户不受影响——他们仍然可以通过其他方式登录(如果能关联到其他 IdP 或设置了密码)

常见错误速查表

错误可能原因优先检查
登录页不显示社交按钮Identity Provider 未启用或 Theme 隐藏了按钮Identity Providers 列表确认状态为 Enabled
invalid_clientClient ID/Secret 错误复制粘贴时是否多了空格/换行
redirect_uri_mismatch回调 URI 配置不对对比平台和 Keycloak 的 URI 是否完全一致(注意 http/https、端口、路径)
登录成功但 Keycloak 报 identity provider not linked本地用户已存在且未关联检查 Users 中是否已有同邮箱用户
可以登录但缺少邮箱/用户名属性映射未配置或 IdP 未返回该字段检查 IdP 的 Mapper 配置,确认 scope 包含了需要的字段
invalid_grant / Token 过期用户长时间未操作这是正常行为,前端需要重新触发登录

IAM 相关阅读