Click here to Skip to main content
15,891,607 members
Articles / Hosted Services / Azure

WCF Security and Authentication in Azure (WsHttpBinding with username and psw credentials)

Rate me:
Please Sign up or sign in to vote.
4.33/5 (2 votes)
15 Apr 2016CPOL2 min read 20.1K   2   1
How to configure WCF service in Azure web app over HTTPS with authentication with few simple steps.

Introduction

I've spent lots of time researching and investigating WCF security in Azure, but couldn't find a working solution directly implemented in Azure web app. Lots of stuff about WCF security in IIS, Azure cloud service (webrole/webworker), but nothing about Azure web application (or web api). So here are some simple steps of setting up HTTPS with basic authentication for WCF which worked for me in Azure web app. 

How To

We will have to take care of two sides of the wire: the WCF Service itself and its Client

The Service

As you probably already know, HTTPS protocol requires SSL sertificate. The good news is that Azure *.azurewebsites.net domains are already secured by a certificate provided by Microsoft. You can use https://mywebsite.azurewebsites.net to access your site securely. Note however, *.azurewebsites.net is a shared domain, and like all shared domains is not as secure as using a custom domain with your own certificate. Enabling HTTPS for an app in Azure App Service with custom domain is beyond the topic of this article and you could find a usefull info in the following resource https://azure.microsoft.com/en-us/documentation/articles/web-sites-configure-ssl-certificate/ 

Web.config

Firstly, let's set up web.config of the server:

<system.serviceModel>
    <services>
      <service name="MyProject.MyService" behaviorConfiguration="serviceBehavior">
        <endpoint address="https://mywebapi.azurewebsites.net/MyService.svc" binding="wsHttpBinding"
           bindingConfiguration="secureHttpBinding" contract="MyProject.Service.Contracts.IMyService" />
      </service>      
    </services>
    <behaviors xdt:Transform="Replace">
      <serviceBehaviors>
        <behavior name="serviceBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" 
                customUserNamePasswordValidatorType="MyNamespace.ClientAuthenticator, MyNamespace" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="secureHttpBinding"
                 hostNameComparisonMode="StrongWildcard"
               receiveTimeout="00:01:00"
               sendTimeout="00:01:00"
               openTimeout="00:01:00"
               closeTimeout="00:01:00"
               maxReceivedMessageSize="2147483647"
               maxBufferPoolSize="524288"
               messageEncoding="Text"
               textEncoding="utf-8"
               bypassProxyOnLocal="false"
               useDefaultWebProxy="true" >
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

Some elements of interest to highlight here:

  1. Endpoint is running over HTTPS (address="https://mywebapi.azurewebsites.net/MyService.svc")
  2. WsHttpBinding endpoint binding configuration has <security> tag with mode="TransportWithMessageCredential" and clientCredentialType="UserName" so that service will expect client credentials in the request. Thus we are enabling WCF Basic Authentication.
  3. ServiceBehavior is set up with ServiceCredentials by means of which we say to WCF what method to run to validate client's credentials. In our case it is MyNamespace.ClientAuthenticator.cs class described below.
ClientAuthenticator.cs

Secondly, we'll need an authenticator to validate the client:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Selectors;
using System.Linq;
using System.ServiceModel;
using System.Web;

namespace MyNamespace
{
    public class ClientAuthenticator: UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (null == userName || null == password)
            {
                throw new FaultException("Credential arguments are not supplied");
            }

            var appSettings = ConfigurationManager.AppSettings;
            if (!string.Equals(userName, appSettings["basicAuthUser"], StringComparison.OrdinalIgnoreCase) && !string.Equals(password, appSettings["basicAuthPsw"], StringComparison.Ordinal))
            {
                throw new FaultException("Invalid user and/or password");
            }
        }
    }
}

The Client

Web.config
<system.serviceModel>
    <client>
       <endpoint address="https://mywebapi.azurewebsites.net/MyService.svc" binding="wsHttpBinding"
           bindingConfiguration="secureHttpBinding" contract="MyProject.Client.Contracts.IMyService" />      
    </client>
    <bindings>
      <wsHttpBinding>
        <binding name="secureHttpBinding"
                 hostNameComparisonMode="StrongWildcard"
               receiveTimeout="00:01:00"
               sendTimeout="00:01:00"
               openTimeout="00:01:00"
               closeTimeout="00:01:00"
               maxReceivedMessageSize="2147483647"
               maxBufferPoolSize="524288"
               messageEncoding="Text"
               textEncoding="utf-8"
               bypassProxyOnLocal="false"
               useDefaultWebProxy="true" >
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

Note, there is no way to configure client's credentials in the <system.serviceModel> tag of web.config file, we'll need to set this up in code.

Supplying client credentials
PeopleServiceClient client = new PeopleServiceClient();
var appSettings = ConfigurationManager.AppSettings;
client.ClientCredentials.UserName.UserName = appSettings["basicAuthUser"];
client.ClientCredentials.UserName.Password = appSettings["basicAuthPsw"];

Conclusion

And that's it, you're good to go, WCF web app in Azure is secured. Remember that the Client has to run over HTTPS as well to communicate with WCF in the right way. Hope this article will save you lots of time in researching this topic. Happy programming. 

History

  • 16th April, 2016: 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
Canada Canada
MCP, .NET framework

Comments and Discussions

 
GeneralMy vote of 4 Pin
Luis Leyva21-Apr-17 6:51
Luis Leyva21-Apr-17 6:51 

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.