WCF services with claims-based authentication and authorization

data: 17 czerwca, 2015
czas czytania: 8 min
autor: Tomasz Krawczyk

In the previous article I’ve presented information about Security Token Service (STS). We know how to build sample Active STS and Relying Party Application.
In this article we focus on sample service based on WCF (Windows Communication Foundation), as we will only try to build sample service with claims-based authentication and authorization. All technical aspects connected with security e.g. configuration, certificates, encryption, signature or CRL will be described in details in the next posts.

WCF “ABC”

Windows Communication Foundation (WCF) is a Microsoft framework for building service-oriented applications. “ABC” is the WCF mantra. „ABC” is the key to understanding how a WCF service endpoint is composed.

Figure 1. WCF ABC

Figure 1. WCF ABC
  • The Address specifies where the service is residing.
  • The Binding is how the service is to be used. The Binding specifies: (protocol to use, encoding to use, type of security requirements to be used, such as SSL or SOAP message security)
  • The Contract identifies operations exposed by the service.

WCF and WIF

WCF provides easy integration with WIF, which allows to use WIF’s features, such as the new claims model, support for additional security token types and token handling in WCF services. For integration with WIF, WCF offers dedicated binding WS2007FederationHttpBinding.

How to build WCF service with claims-based authentication and authorization

In this article, we try to build WCF with claims-based authentication and authorization mechanism. Thanks to the previous article we know how to build Active STS and Relying Party application (Figure 2 steps 1-3). Now, we’ll try to accomplish scenario, which is presented in the following diagram (Figure2 steps 4-6).

Figure 2. WCF Service with STS

Figure 2. WCF Service with STS
  1. The client sends a request message to the service (via application). The request message contains received token.
  2. The service validates the security token and processes the request. To validate a token connection between service and STS is not necessary – issuer validation is based on PKI (this mechanism will be further described in another article)
  3. (Optional) The service initializes and sends a response message to the client.

At first, we build and host WCF (with WS2007FederationHttpBinding) service projects (in this article we won’t focus on implementation of WCF services, we assume that we know how to build and run sample WCF service with httpsBinding).

We prepare sample WCF services (SampleServiceOne and SampleServiceTwo) that will be hosted on IIS. The Relying Party application (a WinForm application), which will be a WCF services client, will use a token received from STS to authenticate and authorize. Both services SampleServiceOne and SampleServiceTwo provide the same functionalities (return information about claim identity) and use tokens issued by “trusted” STS.

  var claimsPrincipal = OperationContext.Current.ClaimsPrincipal;
  var identity = claimsPrincipal.Identity as ClaimsIdentity;

Listing 1: Get information about claim identity in WCF

The SampleServiceOne is based on AspNetCompatibilityRequirements to verify client permissions, the SampleServiceTwo explicitly verifies client permissions.

When AspNetCompatibility mode is enabled in WCF services, we can use the PrincipalPermissionAttribute (SampleServiceOne uses this functionality) to verify client’s identity (authenticate and authorize).

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class SampleServiceOne : SampleService, ISampleServiceOne
    {
        public SampleServiceOne()
        {
            ServiceName = "Service One";
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "User", Authenticated = true)]
        public string ComputeResponse(string input)
        {
            return GenerateResponse(input);
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "Admin", Authenticated = true)]
        public string ComputeResponseAdmin(string input)
        {
            return GenerateResponse(input);
        }

        [PrincipalPermission(SecurityAction.Demand, Role = "SuperAdmin", Authenticated = true)]
        public string ComputeResponseSuperAdmin(string input)
        {
            return GenerateResponse(input);
        }
    }

Listing 2: SampleServiceOne implementation

The SampleServiceTwo explicitly verifies user credentials (authenticate and authorize users).

    public class SampleServiceTwo : SampleService, ISampleServiceTwo
    {
        public SampleServiceTwo()
        {
            ServiceName = "Service Two";
        }

        public string ComputeResponse(string input)
        {
            VerifyUserPermissions("User");
            return GenerateResponse(input);
        }

        public string ComputeResponseAdmin(string input)
        {
            VerifyUserPermissions("Admin");
            return GenerateResponse(input);
        }

        public string ComputeResponseSuperAdmin(string input)
        {
            VerifyUserPermissions("SuperAdmin");
            return GenerateResponse(input);
        }

        private void VerifyUserPermissions(string role)
        {
            var claimsPrincipal = OperationContext.Current.ClaimsPrincipal;
            if (!claimsPrincipal.Identity.IsAuthenticated || !claimsPrincipal.IsInRole(role))
            {
                throw new FaultException("Access denied.");
            }
        }
    }

Listing 3: SampleServiceTwo implementation

To run WCF services with WS2007FederationHttpBinding, we have to prepare service configuration. The configuration may look like “in Listing 4 and Listing 5” (all configurations of technical aspects connected with security will be described in the next post).

<ws2007FederationHttpBinding>
        <binding name="">
          <security mode="TransportWithMessageCredential">
            <message algorithmSuite="Default" establishSecurityContext="false";
              issuedKeyType="BearerKey" />
          </security>
        </binding>
        <binding name="WS2007FederationHttpBinding_ISampleServiceTwo">
          <security mode="TransportWithMessageCredential">
            <message establishSecurityContext="false" issuedKeyType="BearerKey">
              <tokenRequestParameters>
                <trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
                  <trust:KeyType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
                  <trust:CanonicalizationAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>
                  <trust:EncryptionAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>
                </trust:SecondaryParameters>
              </tokenRequestParameters>
            </message>
          </security>
        </binding>
      </ws2007FederationHttpBinding>

Listing 4: Sample binding configuration

 <behavior>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceAuthorization principalPermissionMode="Always"  />
          <serviceCredentials useIdentityConfiguration="true">
            <clientCertificate>
              <authentication certificateValidationMode="None" revocationMode="NoCheck" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>

Listing 5: Sample behaviour configuration

STS – Relying Party Application – WCF communication

A Relying Party is an application or service that relies on claims for authentication. In our example RP application is a simple Win Form application. The application sends an issue request to STS and receives Security Token, which is used to authenticate and authorize a user. The issued token is also used to authenticate and authorize client in WCF services. To run WCF method (with WS2007FederationHttpBinding), first, we have to open communication channel using security token. In our example we’ve created a sample service factory, which will create proxy to WCF service.

public class ServiceApiFactory : IDisposable
    {
        private readonly List _activeServices;
        private readonly SecurityToken _authToken;

        public ServiceApiFactory(SecurityToken token)
        {
            _activeServices = new List();
            _authToken = token;
        }

        public void Dispose()
        {
            foreach (var service in _activeServices)
            {
                try
                {
                    service.Close();
                }
                catch (CommunicationObjectFaultedException)
                {
                    service.Abort();
                }
                catch (TimeoutException)
                {
                    service.Abort();
                }
            }
        }

        public T GetService(string endpointConfigurationName)
        {
            var factory = new ChannelFactory(endpointConfigurationName);
            _activeServices.Add(factory);

            return factory.CreateChannelWithIssuedToken(_authToken);
        }
    }

Listing 6: Sample service factory implementation

The ServiceApiFactory requires issued SecurityToken; then it returns proxy to WCF service (with specified WCF service endpoint configuration).

using (var serviceApi = new ServiceApiFactory(_authController.GeToken()))
{
 var client = serviceApi.GetService("WS2007FederationHttpBinding_ISampleServiceOne");
    //...
}

Listing 6: Sample service factory usage

How to run and test a sample solution

To run the sample STS-RP-WCF implementation we should execute the following steps:

  1. Get sample source code from Git repository (Source Code)
  2. Build STS.sln solution
  3. Host SampleServiceOne and SampleServiceTwo project on IIS (use https)
  4. Run Relying Party Application
    1. Login to STS using a user’s name/password credential (The current STS uses authentication mechanism, which verifies if user’s name corresponds to password e.g. user’s name: user, password: user. If a user’s name is Admin, user is assigned to the User and Admin roles; if a user’s name is SuperAdmin, user is assigned to the User, Admin and SuperAdmin roles.
  5. As a user in the role of User or Admin “Call Service 1” and “Call Service 2”
      1. “Call Service 1” (and “Call Service 2”) runs (sequentially) three methods:
        • ComputeResponse – requires client in User’s role
        • ComputeResponseAdmin – requires client in Admin’s role
        • ComputeResponseSuperAdmin – requires client in SuperAdmin’s role
      2. Analyse execution results (the following figures show sample execution results)

    Figure 3. ServiceOne Call -Admin role

    Figure 3. ServiceOne Call – Admin role

    Figure 4. ServiceTwo Call -Admin role

    Figure 4. ServiceTwo Call – Admin role
    1. To verify that security token is issued by trusted STS, remove or comment Issuer thumbprint from SampleServiceTwo (or SampleServiceOne) configuration file and make call to service once again.
<trustedIssuers>
            <!-- Issuer thumbprint. -->
            <!--
            <add thumbprint="5DA000A8A9AE99E5269F283C72911F5D8BE2D6D1";
                 name="Localhost" />
                 -->
 </trustedIssuers>

Listing 7. Commented issuer thumbprint for local STS

Figure 5

Figure 5. ServiceTwo Call – untrusted issuer

Summary

This article explored technical approach to authentication and authorization process based on claims in WCF services via STS. We have implemented working exemplary solution, which demonstrates how integration between WCF and WIF works.

The next article will describe security aspects of authentication and authorization mechanism based on claims. We’ll try to explain Public Key Infrastructure roles in WIF.

Related posts

  1. Introduction to Claims-Based Authentication and Authorization in .NET – how to build Active STS
  2. Introduction to Claims-Based Authentication and Authorization in .NET

Newsletter IT leaks

Dzielimy się inspiracjami i nowinkami z branży IT. Szanujemy Twój czas - obiecujemy nie spamować i wysyłać wiadomości raz na dwa miesiące.

Subscribe to our newsletter

Administratorem Twoich danych osobowych jest Future Processing S.A. z siedzibą w Gliwicach. Twoje dane będziemy przetwarzać w celu przesyłania cyklicznego newslettera dot. branży IT. W każdej chwili możesz się wypisać lub edytować swoje dane. Więcej informacji znajdziesz w naszej polityce prywatności.