You created WebAPI and now you 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 parties, both 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 an 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 where it is located. 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 write your own HTTP module to perform custom authentication.
')
When a host authenticates a 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 the associated Identity object, with information about the user. If the user is authenticated, the Identity.IsAuthenticated property returns true. For anonymous requests, the property returns false.
Use HTTP message handlers for authentication.
Instead of using a host, the authentication logic can be put into an HTTP message handler. In this case, the message handler examines the HTTP request and sets the security context itself.
A few examples of what might require authentication in message handlers:
- HTTP module sees all requests passing through the ASP.NET channel, the handler sees only requests destined for the 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 in self-hosting.
- HTTP modules participate in IIS logging, auditing, etc.
- HTTP modules are run earlier in the request progress chain. If you authenticate with a message handler, the security context will not be set until the handler is started. In addition, the security context returns 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 put into message handlers.
Setting Security Context
If your application performs any authentication-related logic, you must set the 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 the security context:
private void SetPrincipal(IPrincipal principal) { Thread.CurrentPrincipal = principal; if (HttpContext.Current != null) { HttpContext.Current.User = principal; } }
For web hosting, you must set the 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.
Authorization
In the request handler chain, authorization is closer to the controller. This allows for fine-tuning access to resources.
- Authorization filters execute before 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 depending on the user name, returning only those available for it.

Using the attribute [Authorize]
WebAPI provides a built-in authorization filter, AuthorizeAttribute, this filter checks whether the user is authorized. If not, the filter will return the HTTP 401 status code (Unauthorized), without calling the method.
You can apply a filter both globally and at the controller level or at the method level.
Filter at the global level : To limit access to 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:
Filter at the method level : to restrict access to the method, add an attribute to it:
public class ValuesController : ApiController { public HttpResponseMessage Get() { ... }
In addition, you can set a limit on the controller, and allow anonymous access to individual methods using the [AllowAnonymous] attribute. In the following example, access to the Post method is restricted, and the Get method is available for anonymous calls:
[Authorize] public class ValuesController : ApiController { [AllowAnonymous] public HttpResponseMessage Get() { ... } public HttpResponseMessage Post() { ... } }
In the previous examples, the filter allowed access to any authenticated user by prohibiting access only to anonymous users. You can also give access to specific users or roles:
The AuthorizeAttribute filter for WebAPI controllers is in the System.Web.Http namespace. There is a similar filter for MVC controllers in the System.Web.Mvc namespace. This type is not compatible with WebAPI controllers.
Custom filter authorization
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 that is not necessarily user-based or its role.
- IAuthorizationFilter . Implement this interface for asynchronous authorization logic. For example, your authorization assumes asynchronous or network calls (if the logic is tied to processor computing, 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 result of a query 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 someone will be jarred on by anglicisms like 'custom', 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),
here you can read how to enable authorization in it.