2

The Situation

I have an upcoming project where the web pages will be making AJAX calls. External clients will also be provided a REST API. I will be implementing this project using ASP.NET MVC 4 with Web API.

I have seen various examples online where people use the [Authorize] attribute for security. I presume this is whenever Web API is called via AJAX on a web page.

I have also seen various examples where an API key was passed along with each request (via query string or header). I presume this is whenever Web API is called from an external system.

The Questions

Here are the questions that immediately come to mind:

  • Should I be creating a separate controller for internal and external clients?
  • or should I force the web pages to use the same external authentication model?
  • or is there a way that external clients can use the Authorize attribute?
  • or should I somehow support both forms or authentication at the same time?

A Side Note

A colleague pointed out that I might want to deploy the API to a totally different URL than where the web app is hosted. Along the same lines, he pointed out that the external API may need to be more coarse grain or evolve separately.

I don't want to reinvent the wheel, here. This makes me wonder whether I should be using Web API as an internal API for my AJAX calls in the first place or if I should stick to old-school MVC actions with [HttpPost] attributes.

1 Answer 1

5

[Authorize] attribute is not meant only for Ajax. When you apply the [Authorize] attribute to say an action method, what this does is it ensures the identity is authenticated before the action method runs,irrespective of the clients making the request and irrespective of the type of credentials submitted to your API. All it looks for is Thread.CurrentPrincipal. Here is the copy-paste of the code from the Authorize filter.

protected virtual bool IsAuthorized(HttpActionContext actionContext)
{
    ...
    IPrincipal user = Thread.CurrentPrincipal;
    if (user == null || !user.Identity.IsAuthenticated)
    {
        return false;
    }
    ...
}

As you can see, all it does it gets the Thread.CurrentPrincipal and checks if the identity is authenticated. Of course, when you include the roles, there are additional checks.

So, what this means is that you will be able to use different means of authentication as long as Thread.CurrentPrincipal is set as a result of authentication. If you have two handlers (or HttpModules in case of web hosting) or authentication filters in case of Web API 2, you can establish the identity based on different factors. For example, you can have a BasicAuthnHandler and a ApiKeyHandler added to config.Handlers and hence run in the web API pipeline one after the other. What they can do is to look for the credentials and set Thread.CurrentPrincipal. If Authorize header comes in the basic scheme, BasicAuthnHandler will authenticate and set Thread.CurrentPrincipal and if the API key comes in, it does nothing and ApiKeyHandler sets Thread.CurrentPrincipal. Both handlers can create same type of prinicipal say GenericPrinicpal or even different one. It does not matter because all the principals must implement IPrincipal. So, by the time Authorize filter runs, Thread.CurrentPrincipal will be set and authorization will work regardless of how you authenticate. Note: If you web host, you will also need to set HttpContext.User as well, in addition to Thread.CurrentPrincipal.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.