[c#] How can I pass a username/password in the header to a SOAP WCF Service

Answers that suggest that the header provided in the question are supported out of the box by WCF are incorrect. The header in the question contains a Nonce and a Created timestamp in the UsernameToken, which is an official part of the WS-Security specification that WCF does not support. WCF only supports username and password out of the box.

If all you need to do is add a username and password, then Sergey's answer is the least-effort approach. If you need to add any other fields, you will need to supply custom classes to support them.

A somewhat more elegant approach that I found was to override the ClientCredentials, ClientCredentialsSecurityTokenManager and WSSecurityTokenizer classes to support the additional properties. I've provided a link to the blog post where the approach is discussed in detail, but here is the sample code for the overrides:

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);
    }
}

public 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);
    }
}

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

    protected override void WriteTokenCore(System.Xml.XmlWriter writer,
                                            System.IdentityModel.Tokens.SecurityToken token)
    {
        UserNameSecurityToken userToken = token as UserNameSecurityToken;

        string tokennamespace = "o";

        DateTime created = DateTime.Now;
        string createdStr = created.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");

        // unique Nonce value - encode with SHA-1 for 'randomness'
        // in theory the nonce could just be the GUID by itself
        string phrase = Guid.NewGuid().ToString();
        var nonce = GetSHA1String(phrase);

        // in this case password is plain text
        // for digest mode password needs to be encoded as:
        // PasswordAsDigest = Base64(SHA-1(Nonce + Created + Password))
        // and profile needs to change to
        //string password = GetSHA1String(nonce + createdStr + userToken.Password);

        string password = userToken.Password;

        writer.WriteRaw(string.Format(
        "<{0}:UsernameToken u:Id=\"" + token.Id +
        "\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" +
        "<{0}:Username>" + userToken.UserName + "</{0}:Username>" +
        "<{0}:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" +
        password + "</{0}:Password>" +
        "<{0}:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" +
        nonce + "</{0}:Nonce>" +
        "<u:Created>" + createdStr + "</u:Created></{0}:UsernameToken>", tokennamespace));
    }

    protected string GetSHA1String(string phrase)
    {
        SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
        byte[] hashedDataBytes = sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase));
        return Convert.ToBase64String(hashedDataBytes);
    }

}

Before creating the client, you create the custom binding and manually add the security, encoding and transport elements to it. Then, replace the default ClientCredentials with your custom implementation and set the username and password as you would normally:

var security = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement();
    security.IncludeTimestamp = false;
    security.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
    security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;

var encoding = new TextMessageEncodingBindingElement();
encoding.MessageVersion = MessageVersion.Soap11;

var transport = new HttpsTransportBindingElement();
transport.MaxReceivedMessageSize = 20000000; // 20 megs

binding.Elements.Add(security);
binding.Elements.Add(encoding);
binding.Elements.Add(transport);

RealTimeOnlineClient client = new RealTimeOnlineClient(binding,
    new EndpointAddress(url));

    client.ChannelFactory.Endpoint.EndpointBehaviors.Remove(client.ClientCredentials);
client.ChannelFactory.Endpoint.EndpointBehaviors.Add(new CustomCredentials());

client.ClientCredentials.UserName.UserName = username;
client.ClientCredentials.UserName.Password = password;

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to asp.net

RegisterStartupScript from code behind not working when Update Panel is used You must add a reference to assembly 'netstandard, Version=2.0.0.0 No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization How to use log4net in Asp.net core 2.0 Visual Studio 2017 error: Unable to start program, An operation is not legal in the current state How to create roles in ASP.NET Core and assign them to users? How to handle Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause() ASP.NET Core Web API Authentication Could not load file or assembly 'CrystalDecisions.ReportAppServer.CommLayer, Version=13.0.2000.0 WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for jquery

Examples related to wcf

Create a asmx web service in C# using visual studio 2013 WCF Exception: Could not find a base address that matches scheme http for the endpoint WCF Service, the type provided as the service attribute values…could not be found WCF error - There was no endpoint listening at How can I pass a username/password in the header to a SOAP WCF Service The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'NTLM' Content Type application/soap+xml; charset=utf-8 was not supported by service The content type application/xml;charset=utf-8 of the response message does not match the content type of the binding (text/xml; charset=utf-8) maxReceivedMessageSize and maxBufferSize in app.config how to generate a unique token which expires after 24 hours?

Examples related to web-services

How do I POST XML data to a webservice with Postman? How to send json data in POST request using C# org.springframework.web.client.HttpClientErrorException: 400 Bad Request How to call a REST web service API from JavaScript? The request was rejected because no multipart boundary was found in springboot Generating Request/Response XML from a WSDL How to send a POST request using volley with string body? How to send post request to the below post method using postman rest client How to pass a JSON array as a parameter in URL Postman Chrome: What is the difference between form-data, x-www-form-urlencoded and raw

Examples related to soap

No found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: There was no endpoint listening at (url) that could accept the message How to enable SOAP on CentOS SOAP-ERROR: Parsing WSDL: Couldn't load from - but works on WAMP SOAP vs REST (differences) SOAP request to WebService with java How to consume a SOAP web service in Java Sending SOAP request using Python Requests JSON, REST, SOAP, WSDL, and SOA: How do they all link together What is the difference between JAX-RS and JAX-WS?