Archive

Archive for April, 2011

WCF REST tip 2: WebFaultException

April 30, 2011 12 comments

Introduction

SOAP supports propagating exceptions from the service to the client. This is called “faults” and in WCF this is represented by the FaultException class. Exceptions in REST services are represented by a HTTP status code >= 400. Not a lot of people seem to be aware that WCF supports setting HTTP status error codes by throwing a WebFaultException. Most people doing REST in WCF seem to use the StatusCode property of the OutgoingResponse object that can be accessed from the WebOperationContext.

Because the WebFaultException derives from the regular FaultException, it has the advantage that it results in service implementations that can use SOAP based bindings or HTTP based bindings by just changing the web.config or app.config. Just like the regular FaultException, the WebFaultException exists in two versions: a non generic version and a generic version. The non generic version only supports setting the HTTP status code, while the generic version allows to specify a DataContract class that should be send to the client.

Demo WCF service

We will create a small sample WCF service to show usage of the WebFaultException class. The WCF service will always return a HTTP 401 status code along with some more detailed information about the error in JSON format.

The detail for the WebFaultException is very simple, it consists of 2 properties: a reason field and a detailed information field.

namespace JsonErrorMessage.Service
{
    [DataContract]
    public class ErrorData
    {
        public ErrorData(string reason, string detailedInformation)
        {
            Reason = reason;
            DetailedInformation = detailedInformation;
        }

        [DataMember]
        public string Reason { get; private set; }

        [DataMember]
        public string DetailedInformation { get; private set; }
    }
}

The interface of the service is very simple; it consist of only one method:

namespace JsonErrorMessage.Service
{
    [ServiceContract]
    public interface IHelloService
    {
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        void Hello();
    }
}

The implementation of the service is of course very simple:

namespace JsonErrorMessage.Service
{
    public class HelloService : IHelloService
    {
        public void Hello()
        {
            ErrorData errorData = new ErrorData("You are not allowed to access this service.",
                "We don't allow anybody to access this service.");

            throw new WebFaultException<ErrorData>(errorData,
                HttpStatusCode.Unauthorized);
        }
    }
}

And finally the following configuration needs to be added into the web.config or app.config file:

<system.serviceModel>
  <services>
    <service name="JsonErrorMessage.Service.HelloService">
      <endpoint address=""
                binding="webHttpBinding"
                contract="JsonErrorMessage.Service.IHelloService" />
    </service>
  </services>
</system.serviceModel>

Testing the demo WCF service

I will use Fiddler to test the implementation of the WCF service. Fiddler is a free tool to debug HTTP traffic and I highly recommend using it.

Fiddler has a request builder that allows creating HTTP requests very easily:

Fiddler Request Builder

When we execute this HTTP request we get the following result back:

Response Unauthorized JSon

The server returned a 401 error code and the body is our DataContract in JSON format. This is the result that we wanted.

Categories: C#, REST, WCF

Implementing restricted access to a WCF service with the ServiceAuthorizationManager

April 7, 2011 6 comments

Introduction

The IT industry divides security into two parts: authentication and authorization. Authentication verifies that a users is who he claims to be. This can be done in a couple of ways: certificates, username/password, windows credentials, … Authorization will decide what an (authenticated) user is allowed to execute. In this article I will describe a generic implementation to authorize access to a WCF service.

Implementing restricted access to a WCF service can be done in a couple of ways. A first option is to mark methods with the declarative PrincipalPermissionAttribute to restrict access to certain roles or users. An other option is to imperatively check the credentials of the current user.

Both of these methods have the drawback that they result in a lot of duplication when you have multiple service methods. Because duplication is the root of all evil, the creators of WCF have foreseen an extension point in WCF to implement authorization in a generic way: the ServiceAuthorizationManager.

Implementation

Implementing a ServiceAuthorizationManager is straightforward; you need to extend the class “ServiceAuthorizationManager” and you need to override the method “CheckAccessCore”. In this small example, I will restrict access to my service to users of the windows group “Administrators”.

public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        try
        {
            ServiceSecurityContext securityContext = operationContext.ServiceSecurityContext;
            WindowsIdentity callingIdentity = securityContext.WindowsIdentity;

            WindowsPrincipal principal = new WindowsPrincipal(callingIdentity);
            return principal.IsInRole("Administrators");
        }
        catch (Exception)
        {
            return false;
        }
    }
}

Now that our custom ServiceAuthorizationManager has been implemented, we need to hook it into the WCF pipeline. The most easy way to do is, by using the web.config or app.config file.

<system.serviceModel>
	<!-- Define service and endpoints -->

	<behaviors>
		<serviceBehaviors>
			<behavior name="MyServiceBehavior">
				<serviceAuthorization serviceAuthorizationManagerType="MyNamespace.MyServiceAuthorizationManager, MyAssembly" />
			</behavior>
		</serviceBehaviors>
	</behaviors>
</system.serviceModel>

Conclusion

When you test your service, you will notice that every method is secured by our custom ServiceAuthorizationManager implementation. I hope that you agree with me, that the ServiceAuthorizationManager is a clean way to implement authorization at the service level.

Categories: Advanced, C#, WCF