操作步骤详解
这个过程分为三个主要阶段:
阶段一:在 Keycloak 中配置 (作为 IdP)
需要创建一个“客户端”(Client),这个“客户端”就是指 Microsoft Entra ID。
- 登录 Keycloak 管理控制台并选择 的 Realm (领域)。
- 转到 Clients (客户端) > Create client (创建客户端)。
- Client ID (客户端 ID): * 这是 Entra ID 的 SAML "Entity ID"。这个值是固定不变的,必须输入:
urn:federation:MicrosoftOnline
- Client Protocol (客户端协议): 选择 saml。
- 点击 Save (保存)。
- 配置客户端 (SAML 设置):
- Name (名称): 任意填写,例如 "Microsoft Entra ID / M365"。
- Valid Redirect URIs (有效的重定向 URI):
- 这也是一个固定值,是 Entra ID 接收 SAML 响应的“断言消费服务 (ACS)”地址:
https://login.microsoftonline.com/login.srf- Name ID Format (NameID 格式):
- Entra ID 期望的格式是
persistent(持久化的),Entra ID 需要这个和ImmutableId字段进行“锚定”匹配 - Sign Documents (签署文档): 确保为 On (开启)。
- 配置 Mappers (映射器 - 关键步骤):
很难找这个位置,点击client-urn:federation:MicrosoftOnline-dedicated-configure a new mapper
- Entra ID 需要两个特定的 SAML 属性 (Claims) 才能识别用户。需要转到 Mappers 选项卡。
- Mapper 1: UPN (或 Email)
- Name:
IDPEmail,是这个 Mapper 在 Keycloak 内部的名字(自己看的) - Mapper Type: User Property (用户属性)
- Property:
email(或username,取决于 Keycloak 中哪个字段对应 Entra ID 的 UPN),是 Keycloak 从用户数据中“抓取”哪个字段(抓取email字段) - SAML Attribute Name:
IDPEmail(这是 Entra ID 期望的属性名),是当 Keycloak 把这个值(email的值)放入 SAML 票据时,这个票据里的属性“标签”叫什么名字。
- Mapper 2: ImmutableID (不可变 ID)
- 这是最关键的部分。Entra ID 需要一个在两个系统中都唯一且永不改变的 ID 来“锚定”用户。
- 这个 ID 将通过 SAML 的
NameID字段发送。 - 在第 6 步中设置了
Name ID Format为persistent。默认情况下,Keycloak 会使用其内部的用户 GUID (如f81d4fae-...) 作为persistentNameID 的值。这是推荐的做法。无需为此创建 Mapper,只需确保 Mappers 选项卡中没有其他配置覆盖了NameID即可。
- 获取 Keycloak 的元数据:
- 转到 Realm Settings (领域设置) > General (常规) 选项卡。
- 找到 Endpoints (端点) 链接并点击。
- 找到并复制 SAML 2.0 Identity Provider Metadata 的 URL。它看起来像:
- 需要从这个 XML 元数据中提取三个信息,以便在 PowerShell 中使用:
- IssuerUri:
entityID字段的值 (例如.../auth/realms/\<YourRealm\>) - PassiveLogOnUri:
SingleSignOnService且Binding为urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST的Location值。 - SigningCertificate:
X509Certificate标签内的那一长串证书字符串(删除所有换行符)。
.../auth/realms/<YourRealm>/protocol/saml/descriptor
阶段二:在 Entra ID 中配置 (使用 PowerShell)
这是将 Entra ID 域从“托管”(Managed) 转换为“联邦”(Federated) 的地方。
- 安装 Microsoft Graph 模块 (替代 MSOnline)
- 打开一个管理员 PowerShell 窗口。
Install-Module Microsoft.Graph -Force
- 连接到 Entra ID (替代 Connect-MsolService)
- 使用全局管理员帐户登录。
Connect-MgGraph -Scopes "Domain.ReadWrite.All"
- 执行联邦转换 (替代 Set-MsolDomainFederationSettings)
- 将在阶段一(第8步)中获取的值填入以下变量:
# 1. 定义变量 $domainName = "xiaoyia.com" $logonUrl = "https://sso.stat200.net/realms/master/protocol/saml" $issuerUri = "https://sso.stat200.net/realms/master" $logoffUrl = "https://sso.stat200.net/realms/master/protocol/saml" $cert = "MIICmzCCAYMCBgGafb6KyDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjUxMTEzMTUwMjEwWhcNMzUxMTEzMTUwMzUwWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxSubVXpwQ/NLGv86L0l/7eHTktRvO6KK5UBnFmWsHiugX37vE54cq9TX7EG1TOuitX6Lqoz14hwK6gPNwJTQgrPRuRgZIDmOBM0+m0O70hJBRanUXpOjBs8pJX5P4x82o3bpapR+1Y4K9mG6AWg0cijzFsHC6q/AszqS0q4TuYqHefHFSM0XoTXQ+UoKlkCPAeVPagmSbx756iDWV+HBf4O3Oz0jgV1+TSME46+JcUuKHmlTkHVYp706qo2G/tt9PnWQaWi/MB690T5AcJqmyrAxNbhM7g7Ah8w35FYBhVmLsVITUU2Qxcdz4AEd6uowEsjcimksOCcOTbuZ3KVONAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAF65KC3p1wX84oHi5y18RoQ1xPipXVWb5ocZtKMkD1uRdJh5Ll3IlHP+/ep5/qJqz2zk4neoHh0870Mck4d5AQ4pqsnm+HzdHz/Y29wrfsGKmNgWgGmfXpRY6KLymqAYy5zEF2ZfXW3fuQkgVOOMYISRMvRSpjgYkRdjmVJKUQRsQm2ZB3ODQGzbTO8ROTM/RkM+vAgZ+CXwjN7P6tnFVdolSxj1Ml5e+0XtzJvPHmyHUrWBaKvA1JHnd0Cs3m4KkojgQbiC8sU5Cjww8ED5JZkx+vs/hKomHMncfEkWtwCzS2ya3qkMN6qON6eT+BZhY0vxDakvROWSXpLjDZUgjk4=" # 2. 执行 New-MgDomainFederationConfiguration -DomainId $domainName -IssuerUri $issuerUri -PassiveSignInUri $logonUrl -SignOutUri $logoffUrl -SigningCertificate $cert -PreferredAuthenticationProtocol "saml" -FederatedIdpMfaBehavior "acceptIfMfaDoneByFederatedIdp"
- 验证:
- 运行 Get-MgDomainFederationConfiguration -DomainId "xiaoyia.com”
- 应该能看到刚才输入的所有 Keycloak URL 和证书信息,证明配置已生效。
- Entra ID创建用户时报错
AAD认为既然这个域名归 Keycloak 管,那这个用户肯定是从外部(比如 Keycloak 或本地 AD)同步过来的。为了防止认错人,你必须给我一个唯一的身份证号( SourceAnchor 也就是 ImmutableId) 所以必须通过命令行来创建这个用户,把OnPremisesImmutableId填进去
但是OnPremisesImmutableId从哪来
需要在keycloak中添加属性,且勾选required field,这样在创建用户的时候必须要有uuid的值
然后在client中需要将uuid匹配到nameID
# 1. 准备用户信息 $userParams = @{ DisplayName = "SSO User" UserPrincipalName = "sso@stat200.net" # 目标用户名 MailNickname = "sso" UsageLocation = "CN" # 国家代码 AccountEnabled = $true PasswordProfile = @{ Password = "Password123!" # 初始密码 (其实用不到,因为要去Keycloak验证) ForceChangePasswordNextSignIn = $false } # 关键的一行 OnPremisesImmutableId = "uuid-be544fc0-cd6f-410b-9122-a45143419ec9" # 这里的 ID 必须和 Keycloak 发过来的 NameID 一致 } # 2. 连接 Graph (如果没断开可跳过) Connect-MgGraph -Scopes "User.ReadWrite.All" # 3. 更新用户 Update-MgUser @userParams
小技巧:
- Federated 域名用户创建限制
当域名在 Entra ID 中配置为 Federated,创建用户时必须提供 SourceAnchor,否则无法与本地 AD 的
OnPremisesImmutableId 匹配。- 直接 update 会失败的原因
如果在命令行直接更新 Federated 域用户,但 Entra ID 中没有
SourceAnchor,就无法完成匹配,因此会失败。- 解决方案
先创建一个非 Federated 域名的账号(例如
@stat200.net),再通过命令行同步用户信息并传入 OnPremisesImmutableId,最后修改用户属性,将 UPN 改为 Federated 域名(例如 @xiaoyia.com)。测试
- 打开一个浏览器隐私模式。
- 不要输入密码。当 点击 "下一步" 或按 Tab 键时,Entra ID 会检测到
xiaoyia.com是一个联邦域。
- 将被自动重定向到 Keycloak 的登录页面 ( 在
\$logonUrl中设置的地址)。
- 使用 在 Keycloak 中为此用户设置的密码登录。
- Keycloak 验证成功,将 重定向回 Entra ID (
login.srf)。
- Entra ID 验证 SAML 响应,通过
ImmutableId找到匹配的用户,登录成功。
报错
关掉 client signature required!!
跳转不再报错
跳回AAD
成功!!
