Web Apps vs Web Services: 302s and 401s are not always good Friends

Posted by Your DisplayName here! on Least Privilege See other posts from Least Privilege or by Your DisplayName here!
Published on Fri, 10 Feb 2012 18:28:59 GMT Indexed on 2012/03/18 18:20 UTC
Read the original article Hit count: 288

Filed under:

It is not very uncommon to have web sites that have web UX and services content. The UX part maybe uses WS-Federation (or some other redirect based mechanism). That means whenever an authorization error occurs (401 status code), this is picked by the corresponding redirect module and turned into a redirect (302) to the login page. All is good.

But in services, when you emit a 401, you typically want that status code to travel back to the client agent, so it can do error handling. These two approaches conflict.

If you think (like me) that you should separate UX and services into separate apps, you don’t need to read on. Just do it ;)

If you need to mix both mechanisms in a single app – here’s how I solved it for a project.

I sub classed the redirect module – this was in my case the WIF WS-Federation HTTP module and modified the OnAuthorizationFailed method. In there I check for a special HttpContext item, and if that is present, I suppress the redirect. Otherwise everything works as normal:

class ServiceAwareWSFederationAuthenticationModule : WSFederationAuthenticationModule
{
   
protected override void OnAuthorizationFailed(AuthorizationFailedEventArgs
e)
    {
       
base
.OnAuthorizationFailed(e);

       
var isService = HttpContext.Current.Items[AdvertiseWcfInHttpPipelineBehavior
.DefaultLabel];

       
if (isService != null
)
        {
            e.RedirectToIdentityProvider =
false;
        }
    }
}

Now the question is, how do you smuggle that value into the HttpContext. If it is a MVC based web service, that’s easy of course. In the case of WCF, one approach that worked for me was to set it in a service behavior (dispatch message inspector to be exact):

public void BeforeSendReply(
ref Message reply, object
correlationState)
{
   
if (HttpContext.Current != null
)
    {
       
HttpContext.Current.Items[DefaultLabel] = true;
    }
}

HTH

© Least Privilege or respective owner

Related posts about IdentityModel