📜 ⬆️ ⬇️

Authentication and authorization in ASP.NET Web API

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.



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:


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:


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.



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:
 // 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 restrict access to the method, add an 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 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:
 // 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 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:


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.

Source: https://habr.com/ru/post/231807/


All Articles