Office 365 ADFS 身份驗證不適用於子域
一家公司正在使用帶有 ADFS 身份驗證的 Office 365;AD Connect用於目錄同步,ADFS是Windows server 2012 R2版本。
該公司有多個 Active Directory 域:
parent1.com child1.parent1.com child2.parent1.com child3.parent1.com parent2.com ... ...
根域在 Office 365 中配置為聯合域(公共域名和 AD 域名相同);這很好用,使用者可以使用他們的 UPN(例如
user1@parent1.com
)和他們的 AD 密碼登錄到 Office 365。我需要添加對子域的支持;因此,我
child1.parent1.com
通過執行以下命令添加到 Office 365(在使用管理員帳戶連接到 Office 365 之後Connect-MsolService
):New-MsolFederatedDomain -DomainName child1.parent1.com -SupportMultipleDomain
(注意如果我不使用該
SupportMultipleDomain
參數,PowerShell 會給出一個錯誤,說明它是必需的)。然後我繼續在私有和公共 DNS 中添加所有必需的 DNS 記錄;DNS 記錄的 Office 365 驗證報告一切正常。
然後將子域添加到 AD Connect,並執行同步;來自子域的使用者因此出現在 Office 365 中,使用者名如
user1@child1.parent1.com
. 我為他們分配了適當的許可證並嘗試登錄 Office 365 門戶。但是,子域的使用者無法登錄;他們收到“無效請求”錯誤,並附有以下附加詳細資訊:
Correlation ID: b1e47d45-b21c-42e9-9758-265804db7171 Timestamp: 2016-08-10 20:27:48Z AADSTS50107: Requested federation realm object 'http://child1.parent1.com/adfs/services/trust/' does not exist.
ADFS 方面顯然有問題,但我不是這方面的專家,也不是我設置它的人;如何解決此問題,以便子域中的使用者可以成功登錄 Office 365?
該問題幾乎沒有記錄(Technet 部落格文章和Azure AD 的一些文件),但它確實存在,這是由於 ADFS 在某些特定情況下行為不正確(多個頂級聯合域和在混合); 該解決方案涉及編輯 ADFS 聲明規則中的正則表達式,該規則用於建構與使用者的 UPN 關聯的 IssuerUri。引用第二篇文章:
So lets say for example that I have bmcontoso.com and then add corp.bmcontoso.com. This means that the IssuerUri for a user from corp.bmcontoso.com will need to be http://bmcontoso.com/adfs/services/trust. However the standard rule implemented above for Azure AD, will generate a token with an issuer as http://corp.bmcontoso.com/adfs/services/trust which will not match the domain's required value and authentication will fail.
為了解決這個問題,應該編輯 ADFS 中的第三條聲明規則,從
c:[Type == "http://schemas.xmlsoap.org/claims/UPN"] => issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid", Value = regexreplace(c.Value, ".+@(?<domain>.+)","http://${domain}/adfs/services/trust/"));
到
c:[Type == "http://schemas.xmlsoap.org/claims/UPN"] => issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/issuerid", Value = regexreplace(c.Value, "^((.*)([.|@]))?(?<domain>[^.]*[.].*)$", "http://${domain}/adfs/services/trust/"));
但是,請注意,這可能會破壞與其他方案的兼容性,例如父域未聯合的實際第三級聯合域。