Click here to Skip to main content
15,886,036 members
Articles / Programming Languages / C# 3.5
Tip/Trick

WCF Client For Web Services that Require Authorization by HTTP Header

Rate me:
Please Sign up or sign in to vote.
4.17/5 (11 votes)
24 Dec 2023CPOL2 min read 39.4K   10   10
Using OutgoingMessageProperties and OperationContextScope to implement authorization by http header for WCF client that communicates with non WCF-based web services.
This document navigates WCF-based client connections, demonstrating adaptation for third-party web services demanding custom HTTP header-based authorization, enriching interconnectivity methods.

Introduction

Assume you are communicating with a WCF-based service using WCF-based client.

Due to security reasons, client connection usually requires authorization, so the client should provide some credentials for web service.

Basic Authentication mechanism for WCF is described here.

As you can see after creating a WCF client cc for WCF service "Calculator"...

C#
CalculatorClient cc = new CalculatorClient(myBinding, ea);

...it's possible to pass credentials like this:

C#
cc.ClientCredentials.UserName.UserName = "MyUserName";
cc.ClientCredentials.UserName.Password = "MyPassword";

It's quite simple and works fine if client communicates with web service that provides the same authentication mechanism.

However, sometimes you need to connect to third-party web services which provide their own authentication. Besides that, third-party web services can be non WCF-based at all.

In that case, you can still use WCF-based client, but you may need to write some additional code.

Assume the third-party web service requires authorization by http header.

As per this link, it means that client should provide the Authorization header that looks like:

Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l

where QWxhZGRpbjpPcGVuU2VzYW1l is Base64-encoded string that contains credentials - username and password formatted as "username:password" before ones were Base64-encoded.

Basic Authentication mechanism for WCF will not work in that case because WCF client data is encapsulated inside the http request.

That is WCF client data in XML format (envelop) is located in the "data" part of http request, so no one http header can be modified by that data.

The solution to a problem is using OutgoingMessageProperties and OperationContextScope.

Using the Code

Assume you already have WCF-based client cc which communicates with a third-party service Calculator that requires authorization by http header and you want to call method Add mentioned here.

Use this code to do it:

C#
using (new CalculatorOperationContextScope(cc.InnerChannel).ClientChannel(basicHttpAuth))
{
     cc.Add(100, 1);
}

where:

C#
string basicHttpAuth =
string.Format
(
  "Basic {0}", Convert.ToBase64String(new UTF8Encoding().GetBytes("MyUserName:MyPassword"))
);

For .NET 4.6 or greater, you can use:

C#
string basicHttpAuth =
$"Basic {Convert.ToBase64String(new UTF8Encoding().GetBytes("MyUserName:MyPassword"))}";

and CalculatorOperationContextScope is a class that implements authorization by http header:

C#
public class CalculatorOperationContextScope
{
    private readonly OperationContextScope m_scope;

    public CalculatorOperationContextScope(IClientChannel channel)
    {
       m_scope = new OperationContextScope(channel);
    }

    public IDisposable ClientChannel(string basicHttpAuth, 
                                     string customHttpHeaderName = null,
                                     string customHttpHeaderValue = null)
    {
       return new ClientChannelItem
       (m_scope, basicHttpAuth, customHttpHeaderName, customHttpHeaderValue);
    }

    private class ClientChannelItem : IDisposable
    {
       private readonly OperationContextScope m_scope;

       public ClientChannelItem(OperationContextScope scope, string basicHttpAuth,
                                  string customHttpHeaderName = null,
                                  string customHttpHeaderValue = null)
       {
          m_scope = scope;

          HttpRequestMessageProperty httpRequestProperty = 
                                     new HttpRequestMessageProperty();

          httpRequestProperty.Headers[HttpRequestHeader.Authorization] = basicHttpAuth;

          if (!string.IsNullOrEmpty(customHttpHeaderName) && 
                                    customHttpHeaderName.Trim().Length > 0)
            httpRequestProperty.Headers.Add(customHttpHeaderName, customHttpHeaderValue);

          OperationContext.Current
          .OutgoingMessageProperties[HttpRequestMessageProperty.Name] = 
                                                       httpRequestProperty;
       }

       public void Dispose()
       {
          m_scope.Dispose();
       }
    }
}

In certain cases, third-party service can require additional http header(s) with specific name(s).

You can pass header name customHttpHeaderName and header value customHttpHeaderValue as optional parameters.

If you don't need support for such headers, simply remove that from code.

The check...

C#
!string.IsNullOrEmpty(customHttpHeaderName) && customHttpHeaderName.Trim().Length > 0

...is for backward compatibility with .NET 3.5.

For .NET 4.0 or greater, you can check:

C#
!string.IsNullOrWhiteSpace(customHttpHeaderName)

History

  • 25th December, 2023: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionThanks a lot Pin
Member 117135281-Sep-21 0:37
Member 117135281-Sep-21 0:37 
AnswerRe: Thanks a lot Pin
NikStar4-Sep-21 9:04
NikStar4-Sep-21 9:04 
QuestionThanks a lot Pin
Steve Declerck29-Jan-20 22:04
Steve Declerck29-Jan-20 22:04 
AnswerRe: Thanks a lot Pin
NikStar5-Mar-20 3:02
NikStar5-Mar-20 3:02 
QuestionAccess to security header in SOAP envelope? Pin
KenRH10-Aug-17 5:00
professionalKenRH10-Aug-17 5:00 
AnswerRe: Access to security header in SOAP envelope? Pin
NikStar10-Aug-17 11:53
NikStar10-Aug-17 11:53 
PraiseRe: Access to security header in SOAP envelope? Pin
KenRH10-Aug-17 18:01
professionalKenRH10-Aug-17 18:01 
GeneralRe: Access to security header in SOAP envelope? Pin
NikStar10-Aug-17 23:23
NikStar10-Aug-17 23:23 
GeneralMy vote of 5 Pin
Modus_Exciter7-Aug-17 3:21
Modus_Exciter7-Aug-17 3:21 
GeneralRe: My vote of 5 Pin
NikStar7-Aug-17 3:43
NikStar7-Aug-17 3:43 
Thanks, Modus!
It's not a very difficult problem really Smile | :)
But that code works and I hope it helps others to save their time.

modified 7-Aug-17 18:54pm.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.