2017-10-16 163 views
0

我能够通过在RequestSecurityToken消息中指定TokenType = SecurityTokenTypes.Saml来请求使用SAML 1.1令牌。我可以将其转换为ClaimsPrincipal并查看声明。使用WIF从WS-Trust STS请求SAML 2.0安全令牌4.5

但是,当我想通过将TokenType更改为命名空间“http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0”来请求SAML 2.0令牌时,我收到了一个包含以下内容的异常。

System.Xml.XmlException: '命名空间 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' 无法从元素中读取KeyIdentifierClause ' 参考”。 自定义KeyIdentifierClauses需要自定义SecurityTokenSerializers, 请参考SDK中的示例。'

我想知道SAML 2.0令牌在被WS-Trust 1.3安全令牌服务请求时是否支持,如果是的话,它是如何请求的?由Microsoft提供的SecurityTokenTypes常量类只包含一个不指定版本的“Saml”,并且足够有趣地引用特定于Microsoft的命名空间。

我知道微软提供了SAML 2.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}\n\n", 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> 

如您所见,WSO2 Identity Server正在返回SAML 1.0和SAML 1.1命名空间的混合体。

+0

我使用WSO2的Identity Server 5.3.0作为WS-信托STS。 – Jeffrey

回答

0

我从来没有使用过WSO Identity Server,但是这个代码在Thinktecture IdentityServer中运行良好。我用您示例中的信息替换了端点地址和领域。

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; 
} 
+0

只看这个我会认为它可以与WSO2身份服务器一起工作,唯一的是它没有在RequestSecurityToken元素中指定一个TokenType。我假设这将它留给STS来返回其默认令牌类型。 – Jeffrey

+0

您是否在Thinktecture Identity Server的响应中获得了SAML 2.0令牌? – Jeffrey

+0

@Jeffrey这是相当长的时间以前,但我认为这总是SAML 2.0断言。正如你所说IdentityServer默认设置为发行SAML 2.0令牌。 – pepo

0

可以从WS-信托1.3 STS得到SAML2.0令牌,但请记住:

  1. 这是到STS兑现你的要求。例如,它可能会始终生成特定类型的令牌,无论请求是什么。
  2. 并非所有的STS都可以生成SAML2.0令牌。我知道WIF 4.5允许,但是你的STS使用它吗?我不确定旧版本(WIF 1.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"