Provides a high level overview of some security options with Azure and WCF. Including implementing a WCF service that depends on Azure Storage MembershipProvider and RoleProvider. Also talks about another option using Access Control Services and the Azure Service Bus.

High Level Overview and Goal

Let’s explain a couple things up front – what we are after is a secure WCF service hosted in Azure. What is secure? Considering the architectural constraints and the nature of Azure we can reference the guidance produced by the P&P team for choosing our security model for Azure.

Security Options & Guidance for WCF

Azure fundamentally isn’t any different than a WCF service hosted on premise. You have all the same options, except for one – by default when you deploy your WCF services they will be exposed to the internet and because of that you have some additional constraints you may not otherwise have if you were developing point-to-point services on-premise.

That’s not to say you can’t have line-of-business services running in the cloud, there is a way through the Azure AppFabric Service Bus, but this post wont focus on it. Before we continue let’s talk about our two options in detail.

Public Facing WCF Scenario

public

With a public facing deployed service (default in Azure) we have a WCF service exposed to the entire world on port 80 or 443. This is a standard deployment that is covered by WCF using configuration. If you don’t mind your services being exposed publicly than you can continue reading this particular post as it goes over securing this type of scenario.

Private Service Using the AppFabric Service Bus

servicebus

If you want your WCF services “in-accessible” to the public internet yet still hosted in the cloud we can include the addition of the Azure AppFabric Service Bus.

With the Azure service bus we can create WCF instances in Azure and publish them to the service bus. We get the benefit of the cloud but have a bit more control over the total surface area. In classic P&P style below is a pro/con list of service bus.

Using an azure service bus for security has the following advantages…

  • Services published to the bus can be published either publicly or privately allowing you finer control over the total surface area of attack possible
  • Services benefit from a singular security model implemented using SAML tokens and claims
  • REST services benefit from leveraging OAuth using WRAP protocol and SWT (simple web tokens) provided by ACS
  • Services are isolated and if a compromise occurred in one service container (Azure Deployment) does not mean the entire system is compromised
  • Services have a higher level of redundancy because they can be distributed
  • Services can be mixed with on-premise to provide a common security platform for all services both enterprise and cloud which allows more flexibility when transitioning some or all infrastructure to the cloud.

Using an azure service bus for security has the disadvantages…

  • Services using the service bus w/ ACS may have reduced performance in comparison to other WCF hosting options because of the total round-trips required.
  • Services using the service bus w/ ACS requires an accessible Secure Token Service (ADFSv2 or custom) which increases operational costs
  • Services using the service bus w/ ACS prevents the use of older ASP.NET Web Services as it uses WS-* for SOAP communication.

Message Based Security

In both examples of security we will likely want to implement message based security. Although, using the service bus may allow you some added flexibility when it comes to this. For the scenario we are going to be focusing on we are looking at an implementation of a public exposed WCF service.

In a later posting I’ll be showing an example of a full implementation of a service bus. Because of the nature of a public exposed service we can go to the guidance from the P&P and be confident in our decision to use message based security. A diagram and a snippet from the P&P bluebooks are listed below;

diagram

Use message security for the following scenarios:

  • You are sending a message to a WCF service, and the message is likely to be forwarded to other WCF services or may be routed through intermediate systems.
  • Your WCF clients are accessing the WCF service over the Internet.

Using message security has following advantages:

  • It provides end-to-end security. Because message security directly encrypts and signs the message, having intermediaries does not break the security.
  • It allows partial or selective message encryption and signing, thus improving overall application performance.
  • Message security is transport-independent and can be used with any transport protocol.
  • It supports a wide set of credentials and claims, including issue token, which enables federated security.

Using message security has following disadvantages:

  • This option may reduce performance compared to transport security because each individual message is encrypted and signed.
  • It does not support interoperability with older ASP.NET Web Services (ASMX) clients because it requires both the client and service to support WS-Security specifications.

Example WCF Service “Architecture”

Before we begin lets go over what we are trying to develop in this demo.

hellosecureworld

This example WCF sevice contains two methods, SayHelloToCurrentUser() and SayHelloToAdmin().

Features:

  • Service operation that when called, will authenticate the current user and return the user’s information stored in the membership provider.
  • Service operation that when called, will authenticate the current user and then demand the user be in the role ‘admin’. If the user is not in the admin role the service faults, if the user is in the role the operation yields a nice “hello world” string.

This example shows both integration with the membershipprovider and the role provider and should allow you to develop most scenarios you come across. Hopefully that is sufficient, if not leave a comment and let me know what you would like to see.

Step 1 – Service Definition

First step is creating the actual service code, I’ve done most of this for you in the downloadable example. But for those online just reading below is the simple code:

IHelloWorldService.cs

using System.ServiceModel;

namespace HelloSecureWorld
{
    [ServiceContract(Namespace="http://example.itcontoso.com/helloworld/2010/03")]
    public interface IHelloWorldService
    {
        /// <summary>
        /// Says the hello to current user that is 'authenticated' to the current instance
        /// of this service.
        /// </summary>
        /// <returns>Returns the current authenticated user calling this service.</returns>
        [OperationContract]
        string SayHelloToCurrentUser();

        /// <summary>
        /// Says hello to an admin user as defined by roles. If the user is not an admin the service
        /// throws an exception of type <see cref="System.ServiceModel.Security.SecurityAccessDeniedException"/>.
        /// </summary>
        /// <returns>Returns a friendly string saying hello to the user; or if
        /// unauthorized throws a <see cref="System.ServiceModel.Security.SecurityAccessDeniedException"/></returns>
        [OperationContract]
        string SayHelloToAdmin();
    }
}

HelloWorldService.cs

using System.Security.Permissions;
using System.ServiceModel;

namespace HelloSecureWorld
{
    [ServiceBehavior(
        Namespace = "http://example.itcontoso.com/helloworld/2010/0",
        AddressFilterMode = AddressFilterMode.Any)]
    public class HelloWorldService : IHelloWorldService
    {
        /// <summary>
        /// Says the hello to current user that is 'authenticated' to the current instance
        /// of this service.
        /// </summary>
        /// <returns>
        /// Returns the current authenticated user calling this service.
        /// </returns>
        public string SayHelloToCurrentUser()
        {
            var user = System.ServiceModel.ServiceSecurityContext.Current;

            if (user == null) throw new FaultException("ERROR => User is not authenticated");
            if (user.IsAnonymous) throw new FaultException("ERROR => User is not anonymous!");

            return "Hello " + user.PrimaryIdentity.Name + "!";
        }

        /// <summary>
        /// Says hello to an admin user as defined by roles. If the user is not an admin the service
        /// throws an exception of type <see cref="System.ServiceModel.Security.SecurityAccessDeniedException"/>.
        /// </summary>
        /// <returns>
        /// Returns a friendly string saying hello to the user; or if
        /// unauthorized throws a <see cref="System.ServiceModel.Security.SecurityAccessDeniedException"/>
        /// </returns>
        [PrincipalPermission(SecurityAction.Demand, Role = "admin")]
        public string SayHelloToAdmin()
        {
            return "Hello Admin User!";
        }
    }
}

All in all it’s pretty straight forward. Notice the use of the PrincipalPermission attribute. Basically we are demanding the current user be in the role of admin. This role will be coming from our role provider.

Step 2 – Configuring Our Azure Membership and Role Provider

First we need to add our membership and role providers to the configuration section in our web.config. These membership and role providers come from the Azure samples library. I went ahead and gave them strong names so that I could use my local IIS to manage my test users (more on that later).

    <!-- membership provider bits (switch to sql to test locally) -->
    <membership defaultProvider="azure">
      <providers>
        <clear/>
        <add name="azure"
             type="Microsoft.Samples.ServiceHosting.AspProviders.TableStorageMembershipProvider, Microsoft.Samples.ServiceHosting.AspProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2f54dc1aaae6e6b8"
             applicationName="HelloWorldWCF"/>
      </providers>
    </membership>
    <!-- Configure the Sql Role Provider -->
    <roleManager enabled="true"
                 defaultProvider="azure" >
      <providers>
        <clear/>
        <add name="azure"
             applicationName="HelloWorldWCF"
             type="Microsoft.Samples.ServiceHosting.AspProviders.TableStorageRoleProvider, Microsoft.Samples.ServiceHosting.AspProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2f54dc1aaae6e6b8" />
      </providers>
    </roleManager>

The azure tables storage membership & role providers require you to supply your Azure Storage Account credentials. You can find this information here.

  <appSettings>
    <add key="TableStorageEndpoint" value="https://yourdomainnamehere"/>
    <add key="AccountName" value="youraccountnamehere"/>
    <add key="AccountSharedKey" value="yourvaluehere/>
  </appSettings>

Step 3 – Integrating WCF with the Membership and Role Providers

Integration of the membership and role provider comes out of the box with WCF. All we need to do is tweek some configuration and add a certificate.

Service Bindings

We need to use wsHttpBinding for credentials in Azure and message based security.

    <bindings>
      <wsHttpBinding>
        <binding name="default">
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

Service Behaviors

We need some additional definitions around service behaviors to configure the X509 certificate used for signing the messages and telling WCF what role / membership providers to use for credential validation and service authN/authZ.

    <behaviors>
      <serviceBehaviors>
        <behavior name="wsHttp">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="azure"/>
          <serviceCredentials>
            <serviceCertificate x509FindType="FindByThumbprint" storeName="My" storeLocation="LocalMachine" findValue="3C 2E 84 7F 08 D0 37 CE DF A8 63 C6 4B E5 C2 BC FF 6B 95 34"/>
            <userNameAuthentication membershipProviderName="azure" userNamePasswordValidationMode="MembershipProvider"/>
          </serviceCredentials>
    </behaviors>

Some important things to note here:

  • serviceAuthorization configuration element tells what role provider to use
  • userNameAuthentication element tells WCF what membership provider to use
  • userNamePasswordValidationMode element tells WCF to actually use the membership provider you have defined
  • serviceCertificate is required because we are using (and are required to use) message based security, this tells WCF what cert to use when signing the message

Service Endpoint Configuration

    <services>
      <service name="HelloSecureWorld.HelloWorldService" behaviorConfiguration="wsHttp">
        <endpoint address=""
                  contract="HelloSecureWorld.IHelloWorldService"
                  bindingNamespace="http://example.itcontoso.com/helloworld/2010/0"
                  binding="wsHttpBinding"
                  bindingConfiguration="default"
                  behaviorConfiguration="wsHttp"/>
      </service>
    </services>

Now that we have defined the configuration you’ll notice the X509 certificate being used by WCF needs to exist on your machine. The thumbprint reference is just a way that WCF can get access to a x509 cert used for message encryption/decryption. An X509 cert it is required (and should be!) because you are using username/passwords over wsHttpBinding.

Step 4 – Setting up a self-signed X509 certificate

I’m not rich, and presumably neither are you. I don’t have money to go purchase a x509 certificate from Thawte or Verisign for my local development, so that being the case I need to create a self signed cert. In the download there is a folder called “cert” which contains a copy of makecert and a useful batch file used to create your certificates.

Generate Certificate

You need to generate your own certificate, modify the permissions on it so your local DevFabric can access it, and then copy it’s thumbprint to your web.config of your WCF service. The below steps over how to do this…

cert

.\certs\setupcert.cmd hellosecureworld /noacl

Permissions and Thumbprint of Your Certificate

Now open up mmc and add/remove the add-in for certificates choosing to use certificates for the computer account.

mmc

You should be able to see your new certificate…

hellosecureworld

We need to give Azure/IIS permissions to the private keys. Right click => “manage private keys” and add the network service account.

acl

Get the thumbprint of your new certificate and copy it to your clipboard for pasting into the web.config.

thumbprint

Now that you have the thumbprint copy and paste it into the web.config of the WCF service configuration element serviceCertificate.

Deploying/Testing Your Service

You should now be ready to test your WCF service. Go ahead and publish it to Azure or to DevFabric.

Included in the download is a hot fix that re-formats the URL. This allows you to use svcutil against your DevFabric and Azure. In a future post I’ll go over this caveat and a solution to it as well as some development scenarios that will allow you to host you DevFabric and keep it running outside of Visual Studio (useful for teams).

 

9 Responses to Azure WCF Security: MembershipProvider/RoleProvider

  1. Rajesh says:

    Sir,

    My name is Rajesh and working on a big project SOA based architect where security is major concern. I have any wcf hosted on Azure but i want to make them secure. I studied a lot about its security and my conclusion is message based with type “UserName” and certificate for sevice. I could able to make that but not find a single example how I will pass my credentials to wcf service. I want to obtain a security token so that there is no need of subsequent request with same username and password. So I want to send my username and password from client and would like to test them against my DB and send the client with token. So can i have some example. Please do take into consideration that my services are on azure

    regards,
    rajesh

    • You should be able to use a asp.net membership provider, role providers, and profile providers in WCF to pass the credentials from the web UI layer to the service layer on your back end and validate the credentials. Azure supports this as your UI deployments talking via SOAP can handle this. Please see my blog entry regarding membership providers with WCF and Azure or try the P&P team site (see codeplex).

      • Maddy says:

        hiii sir,
        I have used the memership provider in wcf also changed the details in webconfig.
        when i m debugging the service i am getting the error “Invalid Hexa Decimal String Format”.
        I have checked the certificate key. It is accurate.
        Please guide me to complete the task.
        Thank You.
        Maddy

    • You seem to want SSO (Single sign on) which requires the use of a token server (either one included in the excellent example provided by codeplex) or to write your own basic version. Personally I would recommend the starter STS project on codeplex which contains a pretty advanced implementation of secure communications.

      http://startersts.codeplex.com/

  2. Rajesh says:

    Terrance,
    Topic: Message based with “UserName” credentials and X.509 certificate.

    I am successful in passing my credentials to service. User name and password are authenticated against userName and password in database. Now I am calling second method of this service but it failed because it goes to validate method first. Why ? Once I am authenticated, why it need me to pass userName again. I understand it may require me get claims but how those claims help me get application not passing credentials again and again.

    Please help me to understand.

    Sincerely,
    Rajesh

  3. Nupur Bakshi says:

    Hello Sir,

    I am developing a project in WCF in which I am using WCF Message Based Security with UserNamePassword Client credentials for authenticating the Client.I have also created X509 certificates and provide access to Claims using Claims Based Authorization.Everything is working fine as When I initially call the method of the service it asks for the authentication of the client and after authenticating the Client it provides access to the method which is accurately done but when I call another method from the same service it again asks for authentication which is creating a problem as I don’t want to authenticate the Client again and again on every method call of the same service.Is there any way to retain the Client Credentials so that I would not have to re-authenticate the Client on every method call.Please help me in this.This is my first project in WCF so please provide me the step by step guidance on how to do it.I will be thankful to you.

  4. Louis Berman says:

    Hi! Do you have any idea of how I can use a certificate for message-based security in the Azure cloud WITHOUT needing to explicitly set the Azure/IIS permissions for the private keys? To do this manually through RDP would be a big deployment nightmare since every time a new instance gets brought up I’d have to RDP into the box. Perhaps there’s a way to do this through a starup task or impersonation?!?

Leave a Reply

Your email address will not be published. Required fields are marked *

*


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Set your Twitter account name in your settings to use the TwitterBar Section.