none
Non schema compliant WSSE username token created RRS feed

  • Question

  • I'm working with a customer who is using WCF to send a web service request with a WSSE username token included.  The token is shown below:
    Code Snippet

        <s:Header>
            <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="x">
                    <u:Created>2008-08-01T11:40:54.000Z</u:Created>
                    <u:Expires>2008-08-01T11:45:54.000Z</u:Expires>
                </u:Timestamp>
                <o:UsernameToken u:Id="uuid-xxxxxxxx">
                    <o:Username>someuser</o:Username>
                    <o:Password o:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">somepassword</o:Password>
                </o:UsernameToken>
            </o:Security>
        </s:Header>


    When my application server tries to validate this, it fails with a message about the Type attribute on Password.  The presence of a namespace declaration seems to cause schema validation failure.

    Similarly, when I try to validate in XMLSpy, schema validation fails with the message

    Code Snippet

    Attribute 'o:Type' is not allowed in element <o:Password>
        Hint: Attribute is neither explicitly allowed nor covered by attribute wildcard {any except http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}.
        Error location: o:Security / o:UsernameToken / o:Password / @o:Type
        Details
            cvc-wildcard-namespace: Wildcard {any except http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd} does not allow the namespace name of 'o:Type'.
            cvc-elt.5.2.1: The element <o:Password> is not valid with respect to the actual type definition 'o:PasswordString'.



    Is WCF creating the token incorrectly or are they interpreting the spec differently?  Other clients I've used do not include the namespace declaration on Type.

    Is there any way to change it to remove the namespace prefix from Type when creating the message?

    Thanks!
    Wednesday, August 13, 2008 7:12 PM

Answers

  • You're correct, WCF is unfortunately generating the token improperly. A bug has been filed for this.

     

    You have a couple options for workarounds

     

    1) Easier—set WSSecurityTokenSerializer.EmitsBspRequiredAttribute = false. This will suppress the Type attribute altogether, in which case it defaults to

    http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText. That's what your currently specifying, but you'll need to be sure the service expects that default and won't need to specify anything else.

     

    2) Harder—write a custom serializer for the Username token to correct this behavior.

     

    Thank you for reporting this.

     

    Peter Kron - MSFT

     

     

    Thursday, August 14, 2008 6:06 PM

All replies

  • You're correct, WCF is unfortunately generating the token improperly. A bug has been filed for this.

     

    You have a couple options for workarounds

     

    1) Easier—set WSSecurityTokenSerializer.EmitsBspRequiredAttribute = false. This will suppress the Type attribute altogether, in which case it defaults to

    http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText. That's what your currently specifying, but you'll need to be sure the service expects that default and won't need to specify anything else.

     

    2) Harder—write a custom serializer for the Username token to correct this behavior.

     

    Thank you for reporting this.

     

    Peter Kron - MSFT

     

     

    Thursday, August 14, 2008 6:06 PM
  • Peter,

     

    Could you please elaborate the workaround option #1 in your message a little bit more? Where and how do you set "WSSecurityTokenSerializer.EmitsBspRequiredAttribute = false"? Can this be done solely through configuration? If not, could you point me to any relevent document or sample codes? Thanks ahead for your help.

     

    Yudong

    Friday, August 15, 2008 4:16 PM
  • Hi!

    I'm wondering whether this bug is going to be fixed soon.
    Also, if I want to generate the proper xml, what exactly should be written? Because only the custom serializer will not solve the problem.
    And EmitsBspRequiredAttribute is set to false and cannot be overwritten as far as I've seen, because it is read only.

    Plams
    Tuesday, October 28, 2008 1:40 PM
  • The workaround is to write out your own xml for the UsernameToken node.


    1. Create custom classes to give you control of the UsernameToken xml


     public class CustomCredentials: ClientCredentials
     {
      public CustomCredentials()
      { }

      protected CustomCredentials(CustomCredentials cc)
       : base(cc)
      {
     
      }

      public override System.IdentityModel.Selectors.SecurityTokenManager CreateSecurityTokenManager()
      {
       return new CustomSecurityTokenManager(this);
      }

      protected override ClientCredentials CloneCore()
      {
       return new CustomCredentials(this);
      }
     }

     internal class CustomSecurityTokenManager : ClientCredentialsSecurityTokenManager
     {
      public CustomSecurityTokenManager(CustomCredentials cred)
       : base(cred)
      {

      }

      public override System.IdentityModel.Selectors.SecurityTokenSerializer CreateSecurityTokenSerializer(System.IdentityModel.Selectors.SecurityTokenVersion version)
      {
       return new CustomTokenSerializer(System.ServiceModel.Security.SecurityVersion.WSSecurity11);
      }
     }

     internal class CustomTokenSerializer : WSSecurityTokenSerializer
     {
      public CustomTokenSerializer(SecurityVersion sv)
       : base(sv)
      {

      }

      protected override void WriteTokenCore(System.Xml.XmlWriter writer, System.IdentityModel.Tokens.SecurityToken token)
      {
       System.IdentityModel.Tokens.UserNameSecurityToken unToken = (System.IdentityModel.Tokens.UserNameSecurityToken)token;
       writer.WriteRaw(
    @"<o:UsernameToken u:Id=""" + token.Id + @""">
     <o:Username>" + unToken.UserName + @"</o:Username>
     <o:Password Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"">" + unToken.Password + @"</o:Password>
    </o:UsernameToken>
    ");
      }
     }



    2. Replace the ClientCredentials with your own:


    myService.ChannelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>();
    myService.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials());



    Reference:
    http://msdn.microsoft.com/en-us/library/ms730868.aspx
    Thursday, March 12, 2009 1:36 PM
  • Anyone succeed theses instruction ? 

    I face still the same problem as WCF still sending  the wrong  SOAP header content to Java based web service (SOA) 

    Sunday, February 17, 2013 7:26 AM