我正在尝试使用 WIF 4.5 和 WS-Trust 从 ADFS 获取 SAML 断言,以便我可以将该断言发送给服务提供商并获取 OAuth 票证。
事实上,我已经能够获得 SAML 断言,但它不是一个有效的断言,因为没有收到来自 SubjectConfirmationData 的 Recipient 属性。这是一个强制性的数据。
我正在控制台应用程序中进行测试(因此它使用我的凭据执行,正如我使用 Fiddler 检查过的,它在接收断言之前执行 Kerberos 协商)。我正在获取令牌(基于RequestSecurityToken 使用 windows 凭据和 .net 4.5 WIF):
public static string GetStsToken()
{
try
{
EndpointReference appliesToEp = new EndpointReference(ENDPOINT_REFERENCE_URI);
EndpointAddress stsEp = new EndpointAddress(
new Uri("https://<ADFS-SERVER>/adfs/services/trust/2005/windowstransport"),
EndpointIdentity.CreateSpnIdentity(ADFS_SPN));
WS2007HttpBinding msgBinding = new WS2007HttpBinding(SecurityMode.Transport, false);
msgBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
msgBinding.Security.Message.EstablishSecurityContext = false;
msgBinding.Security.Message.NegotiateServiceCredential = false;
msgBinding.Security.Message.ClientCredentialType = MessageCredentialType.None;
using (WSTrustChannelFactory factory = new WSTrustChannelFactory(msgBinding, stsEp))
{
factory.Credentials.SupportInteractive = false;
factory.TrustVersion = TrustVersion.WSTrustFeb2005;
RequestSecurityToken myRst =
new RequestSecurityToken(RequestTypes.Issue, KeyTypes.Bearer)
{
AppliesTo = appliesToEp,
TokenType = "urn:oasis:names:tc:SAML:2.0:assertion"
};
IWSTrustChannelContract channel = factory.CreateChannel();
GenericXmlSecurityToken stsToken = channel.Issue(myRst) as GenericXmlSecurityToken;
if (stsToken != null)
{
return stsToken.TokenXml.OuterXml;
}
else
{
// SOME WARNING IS ISSUED
}
}
}
catch (Exception ex)
{
// THE EXCEPTION IS REGISTERED
}
return null;
}
使用此代码,发送的请求如下:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:MessageID>urn:uuid:8c221169-52b2-42bf-87f8-7089b6feb0a9</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://ADFS-SERVER/adfs/services/trust/2005/windowstransport</a:To>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>ENDPOINT_REFERENCE</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<t:KeySize>0</t:KeySize>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:TokenType>urn:oasis:names:tc:SAML:2.0:assertion</t:TokenType>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>
我收到的断言似乎是有效的,但是 SubjectConfirmationData 中缺少收件人,因此,当我将该断言发送给服务提供者时,身份验证失败。
如果我使用向服务器发送 a 的 Web IdP Initiated Login,samlp:AuthnRequest
并解码在这种情况下 ADFS 发出的获得的 SAML 断言(再次使用 Fiddler),则会收到 Recipient 属性,并且 SSO 工作。我可以看到用于获取断言的方法不同(在这种情况下使用了 Web-SSO),但是在这两种情况下,依赖方是相同的,因此发出的断言应该是相似的。
使用 WS-Trust 从 ADFS 获取令牌时,有什么方法可以接收正确的收件人?