Authentication and Authorization in Web API
In this article, I am going to discuss the Authentication and Authorization in Web API. Here I will give you an overview of Authentication and Authorization in Web API and from the next article onwards, we will discuss the practical implementation of Authentication and Authorization in ASP.NET Web API with examples.
Once you create a Web API Service, then the most important thing that you need to take care of is security means you need to control the access to your Web API Services. So let’s start the discussion with the definition of Authentication and Authorization
Authentication is the process of identifying the user. For example, one user lets say James log in with his username and password, and the server uses his username and password to authenticate James.
Authorization is the process of deciding whether the authenticated user is allowed to perform an action on a specific resource (Web API Resource) or not. For example, James (who is an authenticated user) has the permission to get a resource but does not have the permission to create a resource.
The Web API Service assumes that the authentication process should happen in the host Server and we generally host the Web API Service at IIS. The IIS Server uses the HTTP modules for checking the authentication of a user. You can configure your project to use any of the built-in authentication modules which are available in IIS or ASP.NET, or you can also create your own HTTP module to perform custom authentication.
When the host (IIS Server) authenticates the user, it generally creates a principal object (i.e. IPrincipal object) under which the code is going to run. So, once the Principal object (IPrincipal object) is created, then the host (i.e. IIS Server) attach that principal object to the current thread by setting Thread.CurrentPrincipal.
If you are confused at the moment about how the Principal object is created and how the principal object is attached to the current thread, then don’t worry we will discuss all these things in greater detail in our upcoming articles. In this article, I am just going to give you an overview of how authentication and authorization happen in Web API services.
Understanding Principal Object
The Principal object contains two things one is Identity object which actually contains the information about the user and the other one is IsInRole property which is a boolean property and this property is set to true if the user is assigned with any roles else false. The following diagram shows the IPrincipal interface definition.
Let’s have a look at the Identity interface definition which contains the user’s information.
The Identity Object which is a property of Principal Object contains three properties i.e. Name (string type), AuthenticationType (string type), and IsAuthenticated (boolean type). If the user is authenticated, then the Identity.IsAuthenticated property will return true else false. The Name property of the Identity object will store the name of Identity, generally, identity is nothing but the logged-in username. Similarly, the AuthenticationType property returns the type of authentication used to identify the user.
The Identity interface is generally implemented by the GenericIdentity and WindowsIdentity classes. We will discuss how these classes implement the IIdentity interface in our upcoming article.
HTTP Message Handlers for Authentication
Instead of using the host (i.e. IIS Server where the Web API service is hosted) for authentication, you can also write the authentication logic into a custom HTTP Message Handler. In that case, the HTTP Message Handler is going to check the incoming HTTP request for authenticating the user and then sets the Principal Object.
Differences HTTP Message Handler over HTTP Module:
An HTTP Module sees all the incoming requests that go through the ASP.NET pipeline whereas a message handler only sees the incoming requests which are routed to the Web API Service.
It is also possible to select a specific HTTP Message Handler and then you can use that specific HTTP Message Handler for authentication for a specific route.
The HTTP Modules are specific to IIS whereas the HTTP Message Handlers can be used with both web-hosting (within a server) and self-hosting (within an application).
The HTTP Modules participate in IIS logging, auditing, and so on.
Generally, if you don’t want to support self-hosting, then HTTP Module is a better option but if you want to support self-hosting then HTTP Message Handler is a better option.
Setting the Principal Object
If you are going to implement your own custom logic for authenticating the user then you can set the principal object at two places which are as follows:
Thread.CurrentPrincipal. This is the standard way to set the thread’s principal in .NET.
HttpContext.Current.User. This property is specific to ASP.NET.
The following image shows how to create and set the principal object with the current thread. Here I am showing you both the options to set the Principal object.
If you are going to host the Web API service in IIS, then you need to set the principal object in both the places because of the security concerns i.e. security becomes inconsistent. In the case of Self-hosting the HttpContext.Current value is null. To ensure your code is host-agnostic (i.e. to support both web hosting and self-hosting), you need to check for null before assigning the Principal object to the HttpContext.Current as shown in the above image.
The Authorization Process is going to happen before executing the Controller Action Method which provides you the flexibility to decide whether you want to grant access to that resource or not.
We can implement this in ASP.NET Web API by using the Authorization filters which will be executed before the controller action method executed. So, if the request is not authorized for that specific resource, then the filter returns an error response to the client without executing the controller action method.
The following diagram explains the above.
Using the [Authorize] Attribute
The ASP.NET Web API Framework provides a built-in authorization filter attribute i.e. AuthorizeAttribute and you can use this built-in filter attribute to checks whether the user is authenticated or not. If not, then it simply returns the HTTP status code 401 Unauthorized, without invoking the controller action method.
You can apply the above built-in filter at globally, at the controller level, or at the action level.
If you want to check the authentication for all the Web API controllers, then it is better to add the AuthorizeAttribute filter to the global filter list within the Register method of the WebApiConfig class as shown in the below image:
At Controller Level:
If you want to provide authentication for all the action methods of a specific controller, then it is better and recommended to add the Authorize filter at the controller level as shown in the below image.
At Action Level:
If you want to provide authentication for specific action methods of a controller, then it is better to add the Authorize filter attribute to the action method which required authentication as shown in the below image.
Another way of doing this is, restrict the controller by decorating the controller with Authorize filter attribute and then allow anonymous access to the action methods which does not require authentication by using the AllowAnonymous attribute. In the below example, the Post method is restricted, but the Get method allows anonymous access.
As of now, we have discussed two things. If we want to check the authentication before invoking the action method then we need to use the built-in Authorize Filter Attribute. If we want any action method to be accessed by the anonymous users then we need to decorate that action method with AllowAnonymous attribute. Along the way, we can also limit the access to specific users or to users with specific roles.
Restrict by Users:
Restrict by Roles:
NOTE: The points to remember here is that the AuthorizeAttribute filter for Web API is located in the System.Web.Http namespace. In MVC there is also an AuthorizeAttribute filter which is located in the System.Web.Mvc namespace, which is not compatible with Web API controllers.
Authorization Inside a Controller Action
In some scenarios, you might allow a request to proceed, but you need to change the behavior based on the principal. For example, the information that you are going to return from the action depends on the user’s role. Within a controller action method, you can get the current principal object from the ApiController.User property as shown in the below image.
In the next article, I will discuss how to implement ASP.NET Web API Basic Authentication with an example. Here, in this article, I try to give you an overview of Authentication and Authorization in Web API. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.