Security has always been a major concern when we talk about enterprise-level applications. This is truer, when we talk about exposing our business through services. However, if we develop Web API, we can secure some or all parts of an API Service so that only verified users can access the API service ensuring client security. This security in ASP.NET Web API can be achieved using the following authentication and authorization mechanisms.
Authentication is all about the identity of an end user. It is about validating the identity of a user who is accessing our system. The fact that he is authenticated enough to use our resources or not. By using the authentication mechanism, we make sure that every request has proper credentials, and received by the Web API service from the actual client.
Authentication Using Message Handlers
A message handler is a class that receives an HTTP request and returns an HTTP response. Message handlers are derived classes from the abstract class HttpMessageHandler. They are good for cross-cutting concerns that operate at the level of HTTP messages (rather than controller actions). For example, a message handler might:
- read or modify request headers
- add a response header to responses
- validate requests before they reach the controller
In a Web API, typically, a series of message handlers are chained together, forming a pattern called delegating handler.
The order in which these handlers are set up is important as they will be executed sequentially.
The most important handler sits at the very top, guarding everything that comes in. If the checks pass, it will pass this request down the chain to the next delegating handler, and so on.
If all goes well, it will then arrive at the API Controller and execute the desired action. However, if any of the checks fail within the handlers, then the request is denied and a response is sent to the client.
Now let’s write the code for the handlers. Create two message handlers APIKeyHandler and AuthHandler as shown below.
- APIKeyHandler: Handler responsible for intercepting an HTTP request and ensuring its header contains an API key.
- AuthHandler: Handler responsible for authenticating a user’s credentials and roles.
API Key Authentication
In the Web API project, create a folder called MessageHandlers and add a class APIKeyHandler.cs.
The APIKeyHandler.cs inherits from DelegatingHandler, which in turn inherits from HttpMessageHandler. In this override the SendAsync() method which looks for an API key (API_KEY) in the header of every HTTP request and control whether to allow this request to flow down the pipeline and passes the request to the controller only if a valid API key is present in the request header or else or halt the request by sending a custom response.
Now register the handler to our application in the Application_Start method in the Global.asax file.
Now call any method that is exposed through the Web API controllers and we will see “Bad API Key” as response.
Let’s verify that the APIKeyHandler is working alright by creating an HTTP Request with correct headers. For that, create an HTTP header with key value:
“API_KEY” : “X-some-key”
In Mozilla browser plugin called “HTTP Tool” create HTTP request headers here.
The HTTP request is now passed all the way to the controller by the handler.
Once API key check handler is in place it secures the Web API to make sure only those clients who are provided with valid API keys can access this service. Next we will look at how we can implement security based on user roles.
Basic authentication is the most simple and basic form of authenticating HTTP requests. The client sends Base64-encoded credentials in the Authorize header on every HTTP request, and only if the credentials are verified does the API return the expected response. Basic authentication doesn’t require server-side session storage or implementation of cookies as every request is verified by the API.
For verifying user credentials, create an ‘IPrincipal’ object which represents the current security context.
Add a new folder called Security and a new class TestAPIPrincipal.cs in it.
The ‘IIdentity’ object associated with the principal has a property called ‘IsAuthenticated’. If the user is authenticated, this property will return true; otherwise, it will return false.
Create another handler called AuthHandler.cs.
The private method ValidateCredentials checks for decoded username and password values from the HTTP request header, and the SendAsync method intercepts the HTTP request.
If the credentials of the client are valid, then the current IPrincipal object is attached to the current thread, i.e. Thread.CurrentPrincipal and set the HttpContext.Current.User to make the security context consistent which allows to access the current user’s details from anywhere in the application.
Once the request is authenticated, base.SendAsync is called to send the request to the inner handler. If the response contains an HTTP unauthorized header, the code injects a WwwAuthenticate header with the value Basic to inform the client that our service expects basic authentication.
Now register the handler in the Global.Asax class similar to ApiKeyHandler and Make sure that the AuthHandler handler is below the first handler registration to make sure of the right order.