我可以通过在RequestSecurityToken消息中指定TokenType=SecurityTokenTypes.SAML来请求SAML 1.1令牌。我可以将其转换为ClaimsPrincipal并查看索赔。
但是,当我想通过将TokenType更改为命名空间来请求SAML 2.0令牌时"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0",我得到一个异常,包括以下内容。
System.Xml.XmlException:'无法从元素中读取KeyIdentifierClause具有命名空间的"Reference"'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"。自定义密钥标识符子句需要自定义SecurityTokenSerializers,有关示例,请参阅SDK。">
我想知道从WS-Trust 1.3安全令牌服务请求SAML 2.0令牌时是否支持,如果支持,是如何请求的?Microsoft提供的SecurityTokenTypes常量类只包含一个没有指定版本的"Saml",有趣的是,它引用了Microsoft特定的命名空间。
我知道Microsoft已经为SAML2.0令牌提供了支持类,例如Saml2SecurityTokenHandler,但我似乎无法实际从STS请求一个。
下面是我的代码。
using System;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.Xml;
namespace WsTrustActiveSTSClient
{
internal class Program
{
private const string relyingPartyId = "http://localhost/myApp";
private const string stsEndpoint = "https://localhost:9443/services/wso2carbon-sts";
private static void Main(string[] args)
{
WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential, false);
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.EstablishSecurityContext = false;
EndpointAddress endpoint = new EndpointAddress(stsEndpoint);
WSTrustChannelFactory factory = new WSTrustChannelFactory(binding, endpoint);
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.UserName.UserName = "admin";
factory.Credentials.UserName.Password = "admin";
WSTrustChannel channel = (WSTrustChannel) factory.CreateChannel();
RequestSecurityToken rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new EndpointReference(relyingPartyId),
Claims =
{
new RequestClaim("http://wso2.org/claims/givenname"),
new RequestClaim("http://wso2.org/claims/emailaddress")
},
//TokenType = SecurityTokenTypes.Saml
TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"
};
GenericXmlSecurityToken genericXmlSecurityToken = (GenericXmlSecurityToken) channel.Issue(rst, out RequestSecurityTokenResponse rstr);
Console.WriteLine("{0}n{1}nn", genericXmlSecurityToken, genericXmlSecurityToken.TokenXml.OuterXml);
SecurityTokenHandlerCollection tokenHandlers = new SecurityTokenHandlerCollection(
new SecurityTokenHandler[]
{
new SamlSecurityTokenHandler(),
new Saml2SecurityTokenHandler()
}
);
tokenHandlers.Configuration.AudienceRestriction = new AudienceRestriction();
tokenHandlers.Configuration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(relyingPartyId));
TrustedIssuerNameRegistry trustedIssuerNameRegistry = new TrustedIssuerNameRegistry();
tokenHandlers.Configuration.IssuerNameRegistry = trustedIssuerNameRegistry;
SecurityToken token =
tokenHandlers.ReadToken(
new XmlTextReader(new StringReader(genericXmlSecurityToken.TokenXml.OuterXml)));
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(tokenHandlers.ValidateToken(token).First());
Console.WriteLine("Name : " + claimsPrincipal.Identity.Name);
Console.WriteLine("Auth Type : " + claimsPrincipal.Identity.AuthenticationType);
Console.WriteLine("Is Authed : " + claimsPrincipal.Identity.IsAuthenticated);
foreach (Claim c in claimsPrincipal.Claims)
Console.WriteLine("{0}:{1}", c.Type, c.Value);
Console.ReadLine();
}
public class TrustedIssuerNameRegistry : IssuerNameRegistry
{
public override string GetIssuerName(SecurityToken securityToken)
{
return "Trusted Issuer";
// throw new SecurityTokenException("Untrusted issuer.");
}
}
}
}
当我没有在RST中指定TokenType时,这是发送到WS-Trust STS的SOAP消息。
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action>
<a:MessageID>urn:uuid:bb24c76a-b737-4a9b-8526-26b84a28bbe8</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://localhost:9443/services/wso2carbon-sts</a:To>
<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
<u:Timestamp u:Id="_0">
<u:Created>2017-10-17T14:50:01.517Z</u:Created>
<u:Expires>2017-10-17T14:55:01.517Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-b6a803fc-b1fe-4186-8c3e-dcf4b1a647e5-1">
<o:Username>admin</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">admin</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<trust:RequestSecurityToken xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<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>http://localhost/myApp</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<trust:Claims xmlns:i="http://schemas.xmlsoap.org/ws/2005/05/identity" Dialect="http://schemas.xmlsoap.org/ws/2005/05/identity">
<i:ClaimType Uri="http://wso2.org/claims/givenname" Optional="false"/>
<i:ClaimType Uri="http://wso2.org/claims/emailaddress" Optional="false"/>
</trust:Claims>
<trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
<trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>
</trust:RequestSecurityToken>
</s:Body>
</s:Envelope>
以下是WSO2 Identity Server的响应。
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="true">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-1">
<wsu:Created>2017-10-17T14:50:02.407Z</wsu:Created>
<wsu:Expires>2017-10-17T14:55:02.407Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
<wsa:Action>http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/Issue</wsa:Action>
<wsa:RelatesTo>urn:uuid:bb24c76a-b737-4a9b-8526-26b84a28bbe8</wsa:RelatesTo>
</soapenv:Header>
<soapenv:Body>
<wst:RequestSecurityTokenResponseCollection xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<wst:RequestSecurityTokenResponse>
<wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</wst:TokenType>
<wst:RequestedAttachedReference>
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_d8c5ef71f6665284b3ba5f7aca69f08b</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</wst:RequestedAttachedReference>
<wst:RequestedUnattachedReference>
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_d8c5ef71f6665284b3ba5f7aca69f08b</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</wst:RequestedUnattachedReference>
<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>http://localhost/myApp</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<wst:Lifetime>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2017-10-17T14:50:02.236Z</wsu:Created>
<wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2017-10-17T14:55:02.236Z</wsu:Expires>
</wst:Lifetime>
<wst:RequestedSecurityToken>
<Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" AssertionID="_d8c5ef71f6665284b3ba5f7aca69f08b" IssueInstant="2017-10-17T14:50:02.282Z" Issuer="https://localhost" MajorVersion="1" MinorVersion="1">
<Conditions NotBefore="2017-10-17T14:50:02.236Z" NotOnOrAfter="2017-10-17T14:55:02.236Z">
<AudienceRestrictionCondition>
<Audience>http://localhost/myApp</Audience>
</AudienceRestrictionCondition>
</Conditions>
<AuthenticationStatement AuthenticationInstant="2017-10-17T14:50:02.236Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password">
<Subject>
<NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin</NameIdentifier>
<SubjectConfirmation>
<ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</ConfirmationMethod>
</SubjectConfirmation>
</Subject>
</AuthenticationStatement>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#_d8c5ef71f6665284b3ba5f7aca69f08b">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="code ds kind rw saml samlp typens #default xsd xsi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>8w9YHsb+YIyUCzGjqh6q0JrjxTI=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>Evm0H2+hOMWdsrK0Rp8HPCDDldMJ+AHPgv4hrqKW6IuPGFT25DhTRoIc+cPuerFOABYX5B1Om0v4VlmqsalpK2V7tdzHlrDbrOCiENL4FhdATd48o/IiRjde8XM0B7gHAIJoMSimg3Fc/jPXH4kyMsLAWM+l0GdK8VxKVLPtrhY=</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIICNTCCAZ6gAwIBAgIES343gjANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxDTALBgNVBAoMBFdTTzIxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xMDAyMTkwNzAyMjZaFw0zNTAyMTMwNzAyMjZaMFUxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzENMAsGA1UECgwEV1NPMjESMBAGA1UEAwwJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUp/oV1vWc8/TkQSiAvTousMzOM4asB2iltr2QKozni5aVFu818MpOLZIr8LMnTzWllJvvaA5RAAdpbECb+48FjbBe0hseUdN5HpwvnH/DW8ZccGvk53I6Orq7hLCv1ZHtuOCokghz/ATrhyPq+QktMfXnRS4HrKGJTzxaCcU7OQIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEAW5wPR7cr1LAdq+IrR44iQlRG5ITCZXY9hI0PygLP2rHANh+PYfTmxbuOnykNGyhM6FjFLbW2uZHQTY1jMrPprjOrmyK5sjJRO4d1DeGHT/YnIjs9JogRKv4XHECwLtIVdAbIdWHEtVZJyMSktcyysFcvuhPQK8Qc/E/Wq8uHSCo=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</Assertion>
</wst:RequestedSecurityToken>
</wst:RequestSecurityTokenResponse>
</wst:RequestSecurityTokenResponseCollection>
</soapenv:Body>
</soapenv:Envelope>
正如您所看到的,WSO2Identity Server正在返回SAML1.0和SAML1.1命名空间的混合体。
我从未使用过WSO Identity Server,但这段代码与Thinktecture Identity Server配合得很好。我已经用您的示例中的信息替换了端点地址和领域。
public static SecurityToken GetToken(string userName, string password)
{
const string stsEndpoint = "https://localhost:9443/services/wso2carbon-sts";
const string realm = "http://localhost/myApp";
var factory = new WSTrustChannelFactory(
new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
stsEndpoint) { TrustVersion = TrustVersion.WSTrust13 };
factory.Credentials.UserName.UserName = userName;
factory.Credentials.UserName.Password = password;
var rst = new RequestSecurityToken
{
AppliesTo = new EndpointReference(realm),
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer
};
var channel = factory.CreateChannel();
var token = channel.Issue(rst);
return token;
}
您可以从WS-Trust 1.3 STS获得SAML2.0令牌,但请记住:
- 由STS来满足您的请求。例如,无论请求什么,它都可能始终生成特定类型的令牌
- 并非所有STS都能生成SAML2.0令牌。我知道WIF 4.5允许这样做,但您的STS使用它吗?我不确定旧版本(WIF1.0/3.5)是否可以生成SAML2.0令牌
假设您的特定STS确实满足这些请求,并且可以生成SAML2.0令牌,那么请尝试以下操作:
TokenType = "urn:oasis:names:tc:SAML:2.0:assertion"
或者,如果它仍然不起作用,也许:
AuthenticationType = "urn:oasis:names:tc:SAML:2.0:assertion"
我偶尔发现,将RST的tokenType设置为saml2.0 URL会使STS返回saml2.0断言。最有趣的事情莫过于微软的文档。
试试这样的东西:
ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
var rst = new RequestSecurityToken(RequestTypes.Issue);
rst.AppliesTo = new EndpointReference("https://RelyingParty/*");
rst.KeyType = KeyTypes.Bearer;
rst.TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0";
using (var trustChannelFactory = new WSTrustChannelFactory("WS2007HttpBinding_IWSTrust13_Saml20Sync"))
{
trustChannelFactory.Credentials.UserName.UserName = userName;
trustChannelFactory.Credentials.UserName.Password = userPassword;
var channel = (WSTrustChannel)trustChannelFactory.CreateChannel();
try
{
_authToken = channel.Issue(rst);
}
catch (MessageSecurityException ex)
{
channel.Abort();
throw new SecurityTokenException(ex.InnerException.Message, ex);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
UserIdenity = CreateUserIdentityFromSecurityToken(_authToken);
}