Authentication and Authorization in ASP.NET Web API

Original author: Mike Wasson
  • Transfer
  • Tutorial
Have you created WebAPI and now want to control access to it? In this series of articles, we will look at several options for protecting WebAPI from unauthorized users. The series will cover both sides, and user authentication and authorization.

  • Authentication - allows you to uniquely identify the user. For example, Alice logs in with her username and password, and the server uses this data to authenticate Alice.
  • Authorization decides whether the user can perform certain actions. For example, Alice may have the right to read a resource, but cannot create a new resource.


The first series of articles provides a general overview of authentication and authorization in the ASP.NET Web API. Other articles describe common authentication scenarios for WebAPI.

Authentication


WebAPI assumes that authentication is performed by the host on which it is hosted. For web hosting, the host is IIS, which uses HTTP modules for authentication. You can configure your project to use authentication modules built into IIS or ASP.NET, or you can write your own HTTP module to perform custom authentication.

When the host authenticates the user, it creates an IPrincipal object, which is the security context in which the code is executed. The created object attaches to the current thread, and can be accessed through the Thread.CurrentPrincipal property. The security context contains an associated Identity object with user information. If the user is authenticated, the Identity.IsAuthenticated property will return true. For anonymous requests, the property will return false.

Using HTTP message handlers for authentication.


Instead of using a host, authentication logic can be placed in an HTTP message handler. In this case, the message handler examines the HTTP request and sets the security context.

A few examples of why authentication in message handlers might be needed:
  • The HTTP module sees all requests passing through the ASP.NET channel, the handler sees only requests destined by WebAPI
  • You can install separate message handlers for each route using different authentication schemes.
  • HTTP modules are specific to IIS. Message handlers are independent of the host, and can be used both in the case of web hosting and self-hosting.
  • HTTP modules participate in IIS logging, auditing, etc.
  • HTTP modules run earlier in the request chain. If you authenticate with the message handler, the security context will not be set until the handler starts. In addition, the security context reverts to the previous state when the response to the request leaves the message handler.


In general, if you are not going to use self-hosting, using HTTP authentication modules is the best option. Otherwise, the logic should be moved to message handlers.

Setting Security Context


If your application performs any authentication-related logic, you must specify a security context in two properties:
  • Thread.CurrentPrincipal - The standard way to set the security context for a thread in .NET
  • HttpContext.Current.User - property specific to ASP.NET


The following code shows how to set a security context:
private void SetPrincipal(IPrincipal principal)
{
    Thread.CurrentPrincipal = principal;
    if (HttpContext.Current != null)
    {
        HttpContext.Current.User = principal;
    }
}


For web hosting, you must specify a security context in both properties, otherwise the security context may become inconsistent. To ensure that your code is independent of the hosting method, you should set a null check for the HttpContext.Current property, as shown in the code. In the case of self-hosting, its value will be null and no security context is required.

Login


In the chain of request handlers, authorization is closer to the controller. This allows you to fine-tune access to resources.
  • Authorization filters work out to controller methods. If the request is not authorized, the filter will return an error message, and the controller method will not be called.
  • In the controller method, you can get the current security context from the ApiController.User property. For example, you can filter the list of resources by user name, returning only those available to him.



Using Attribute [Authorize]


WebAPI provides a built-in authorization filter, AuthorizeAttribute, this filter checks if the user is authorized. If not, the filter will return an HTTP 401 status code (Not authorized), without calling the method.
You can apply the filter both globally and at the controller level or at the method level.

Filter at the global level : To restrict access for each WebAPI controller, add the AuthorizeAttribute filter to the global filter list:
public static void Register(HttpConfiguration config)
{
    config.Filters.Add(new AuthorizeAttribute());
}


Filter at the controller level : to restrict access to a specific controller, add a filter as an attribute of the controller class:
// Require authorization for all actions on the controller.
[Authorize]
public class ValuesController : ApiController
{
    public HttpResponseMessage Get(int id) { ... }
    public HttpResponseMessage Post() { ... }
}


Filter at the method level : to limit access to the method, add the attribute to it:
public class ValuesController : ApiController
{
    public HttpResponseMessage Get() { ... }
    // Require authorization for a specific action.
    [Authorize]
    public HttpResponseMessage Post() { ... }
}


In addition, you can set a restriction on the controller, and allow anonymous access to individual methods using the [AllowAnonymous] attribute. In the following example, access to the Post method is limited, and the Get method is available for anonymous calls:
[Authorize]
public class ValuesController : ApiController
{
    [AllowAnonymous]
    public HttpResponseMessage Get() { ... }
    public HttpResponseMessage Post() { ... }
}


In previous examples, the filter allowed access to any authenticated user, denying access only to anonymous users. You can also grant access to specific users or roles:
// Restrict by user:
[Authorize(Users="Alice,Bob")]
public class ValuesController : ApiController
{
}
// Restrict by role:
[Authorize(Roles="Administrators")]
public class ValuesController : ApiController
{
}


The AuthorizeAttribute filter for WebAPI controllers is located in the System.Web.Http namespace. There is a similar filter for MVCs in the System.Web.Mvc namespace. This type is not compatible with WebAPI controllers.


Custom authorization filter


A custom filter must be inherited from one of the following types:
  • AuthorizeAttribute . Inherit this class to implement synchronous authorization logic based on the current user or user role.
  • AuthorizationFilterAttribute . This class is useful for implementing authorization logic, not necessarily based on the user or his role.
  • IAuthorizationFilter . Implement this interface for asynchronous authorization logic. For example, your authorization involves asynchronous or network calls (if the logic is based on processor calculations, it is better to inherit from AuthorizationFilterAttribute so as not to write asynchronous methods)


The following diagram shows the hierarchy of filter classes:


Authorization inside the controller method


In some cases, you can allow the execution of the request, but change the behavior based on the security context. For example, the query result depends on the role of the user. Inside the controller method, you can get the current security context by accessing the ApiController.User property:
public HttpResponseMessage Get()
{
    if (User.IsInRole("Administrators"))
    {
        // ...
    }
}


* The translation is made in a free style, perhaps anglicisms like “custom” will distort someone, but these words have become part of it jargon, and the Russian translation is not perceived as it should.

PS If you want to debug with authorization in the studio, on the local IIS (Local IIS Web server), then here you can read how to enable authorization in it.

Only registered users can participate in the survey. Please come in.

To develop the topic of access control in WebAPI further?

  • 94.5% Yes 207
  • 5.4% No 12

Also popular now: