Authentication and Authorization in ASP.NET Web API
In this article, I will discuss Authentication and Authorization in ASP.NET Web API. Here, I will give you an overview of Authentication and Authorization in ASP.NET Web API. From the next article onwards, we will discuss the practical implementation of Authentication and Authorization in ASP.NET Web API with Examples.
What are Authentication and Authorization in Web API?
Once you create a Web API Service, the most important thing you need to take care of is security, which means you need to control access to your Web API Services. So, let’s start the discussion with the definition of Authentication and Authorization. Authentication and authorization are critical to building secure web applications, including ASP.NET Web API applications. Authentication is the process of verifying the identity of a user. At the same time, Authorization determines what actions and resources the Authenticated user is allowed to access based on their identity and roles. Authentication is performed first, and then Authorization.
Authentication in Web API:
Authentication is the process of identifying the user. For example, one user, let’s say, James, logs in with his username and password, and the server uses his username and password to authenticate James. Common authentication mechanisms for Web APIs include:
- Bearer Token Authentication: Clients include a token (e.g., JWT or OAuth token) in the request headers, which the server validates.
- Basic Authentication: Clients send a username and password with each request, typically encoded in Base64 format.
- API Key Authentication: Clients include an API key in the request, validated on the server.
- OAuth 2.0: OAuth 2.0 is a framework for securing APIs. It allows clients to obtain access tokens used to authenticate requests.
- Custom Authentication: You can implement custom authentication logic based on your requirements.
- Windows Authentication: If you are running your application in a Windows environment, you can use Windows Authentication to authenticate users based on their Windows credentials.
Authorization in Web API:
Authorization is deciding whether the authenticated user can perform an action on a specific resource (Web API Resource). For example, James (an authenticated user) has permission to get a resource but does not have permission to create a resource. So, once a user is authenticated, you can implement authorization by defining Roles and Policies or using attributes in your controllers and actions.
- Role-Based Authorization: You can use role-based authorization to restrict access to specific resources or actions based on the user’s role. Users are assigned roles (e.g., “Admin,” “User”) that determine their access rights. You can decorate controllers or actions with the [Authorize(Roles = “RoleName”)] attribute.
- Policy-Based Authorization: You can define and apply custom policies to controllers or actions. Policies can be based on a combination of roles, claims, or custom requirements. Policies are defined with specific access requirements, and endpoints are protected using the [Authorize(Policy = “PolicyName”)] attribute.
- Claim-Based Authorization: Resource access is based on the user’s claims in claims-based authorization. You can use the [Authorize] attribute with specific claims as parameters.
- Custom Authorization: For more complex scenarios, you can implement custom authorization logic by extending the authorization framework or implementing custom middleware.
Authentication in ASP.NET Web API
The ASP.NET Web API Service assumes that the authentication process should happen in the host Server, and we generally host the ASP.NET Web API Service at IIS. The IIS Server uses the HTTP Modules to check a user’s authentication. You can configure your project to use any of the built-in authentication modules available in IIS or ASP.NET or 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 will run. So, once the Principal object (IPrincipal object) is created, the host (i.e., IIS Server) attaches that Principal Object to the Current Thread by setting Thread.CurrentPrincipal.
If you are confused about how the Principal object is created and how the principal object is attached to the current thread, don’t worry; we will discuss all these things in greater detail in our upcoming articles. This article will give you an overview of how authentication and authorization happen in Web API services.
Understanding Principal Object
The IPrincipal Interface contains two things: the Identity object, which contains the information about the user, and the other one is the IsInRole property, which is a boolean property. This boolean property is set to true if the user is assigned any roles else false. The following diagram shows the IPrincipal interface definition.
Let’s look at the Identity interface definition, which contains the user’s information.
The Identity Object, which is a property of the Principal Object, contains three properties, i.e., Name (string type), AuthenticationType (string type), and IsAuthenticated (boolean type). If the user is authenticated, the IsAuthenticated property will return true; otherwise, it will return false. The Name property of the Identity object will store the name of the 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 GenericIdentity and WindowsIdentity classes generally implement the Identity interface. Our upcoming article will discuss how these classes implement the IIdentity interface.
HTTP Message Handlers for Authentication in Web API
Instead of using the host (i.e., IIS Server, where the ASP.NET 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 will check the incoming HTTP request for authenticating the user and then set the Principal Object.
Differences Between 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 routed to the ASP.NET Web API Service.
It is also possible to select a specific HTTP Message Handler and then use it 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. I am showing you both options to set the Principal object here.
Suppose you are going to host the Web API service in IIS. In that case, you need to set the principal object in both places because of the security concerns, i.e., security becomes inconsistent when Self-hosting the HttpContext.Current value is null. To ensure your code is host-agnostic (i.e., to support web hosting and self-hosting), you must check for null before assigning the Principal object to the HttpContext.Current, as shown in the above image.
Authorization in ASP.NET Web API
The Authorization Process will happen before executing the Controller Action Method, allowing you to decide whether you want to grant access to that resource.
We can implement this in ASP.NET Web API using the Authorization filters, which will be executed before the controller action method is 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 check whether the user is authenticated. If not, it returns the HTTP status code 401 Unauthorized without invoking the controller action method. You can apply the Authorize filter globally, or at the controller or action levels.
Suppose you want to check the authentication for all the Web API controllers. In that case, 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 image below:
At Controller Level:
Suppose you want to provide authentication for all the action methods of a specific controller. In that case, adding the Authorize filter at the controller level is better and recommended, as shown in the image below.
At Action Level:
Suppose you want to provide authentication for specific action methods of a controller. In that case, adding the Authorize filter attribute to the action method that requires authentication is better, as shown in the image below.
Another way of doing this is to restrict the controller by decorating the controller with the Authorize filter attribute and then allowing 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, we need to use the built-in Authorize Filter Attribute. If we want any action method to be accessed by anonymous users, then we need to decorate that action method with the AllowAnonymous attribute. Along the way, we can limit access to specific users or users with specific roles.
Restrict by Users:
Restrict by Roles:
Note: The point to remember here is that the AuthorizeAttribute filter in ASP.NET Web API is located in the System.Web.Http namespace. In MVC, there is also an AuthorizeAttribute filter located in the System.Web.Mvc namespace, which is not compatible with ASP.NET 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 you will return from the action depends on the user’s role.
In the next article, I will discuss how to implement ASP.NET Web API Basic Authentication with an example. In this article, I try to give you an overview of Authentication and Authorization in ASP.NET Web API. I hope this article will help you with your needs. I would like to have your feedback. Please post your feedback, questions, or comments about this article. If you want to learn C# in depth, please look at our C# in Depth with Architecture tutorials. We believe you will enjoy this course.
About the Author: Pranaya Rout
Pranaya Rout has published more than 3,000 articles in his 11-year career. Pranaya Rout has very good experience with Microsoft Technologies, Including C#, VB, ASP.NET MVC, ASP.NET Web API, EF, EF Core, ADO.NET, LINQ, SQL Server, MYSQL, Oracle, ASP.NET Core, Cloud Computing, Microservices, Design Patterns and still learning new technologies.