Search code examples
c#.netwcfrestwcf-rest-contrib

Enabling 401 Challenge responses when using WebAuthenticationConfiguration


I have a very simple WCF4 Restful web service which uses WcfRestContrib to allow custom Basic Authentication. It works great when the client preemptively supplies a username and password but if they don't it returns a 400 Bad Request response rather than challenging the client to supply credentials (through a 401 response).

The service is using the declarative approach to implementing WcfRestContrib by decorating the necessary classes with Attributes. Here is my ServiceContract declaration:

// Standard attributes here
[WebAuthenticationConfiguration(typeof(WebBasicAuthenticationHandler),
                                typeof(SecurityValidator),
                                false,
                                "SearchService")
]
public class SearchService

Which only has one very simple operation:

// Standard attributes here
[OperationAuthentication]
SearchResponse Fetch(SearchRequest request)

And my UserNamePasswordValidator looks like (though it probably doesn't matter since it only gets called when credentials are passed):

public override void Validate(string userName, string password)
{
    // TODO: Insert login validation logic here.

    // To indicate login failure, throw a FaultException
    // throw new FaultException("Unknown Username or Incorrect Password");

    // Just return to indicate that the username and password are valid
    return;
}

I tried to debug WcfRestContrib and found that the WebBasicAuthenticationHandler class is throwing a BasicAuthorizationException (which is only caught in framework code), however, for some reason it isn't transforming the exception into a 401.

Based on what I've read on the WcfRestContrib github site, there is an issue posted by its author (Mike O'Brian) saying that he'd like to see it return anything other than a 401 which I read as it currently returns the 401 challenge.

If this functionality is there then what am I missing, or am I doing something else wrong?

UPDATE

If there is not a way to do this with WcfRestContrib, is there an alternative way to achieve this (beyond using the standard Windows-based Basic Authentication in IIS)? I'm open to any (other) alternative solution.


Solution

  • I figured it out. I needed to decorate my ServiceContract with the ErrorHandlerAttribute:

    // Standard attributes here
    [WebAuthenticationConfiguration(typeof(WebBasicAuthenticationHandler),
                                typeof(SecurityValidator),
                                false,
                                "SearchService"),
     ErrorHandler(typeof(WebErrorHandler))]
    public class SearchService
    

    Just by adding the [ErrorHandler(typeof(WebErrorHandler))] attribute to the service makes all of the magic happen. I knew it had to be something simple, just wish I would have seen it before flattening my forehead on my desk.