Hi folks,
Now we will discuss a very nice problem which generally happens when we use the Web API.
The problem is authorization and authentication for Web API resources.
Problem: We have a set of methods and a few of them are exposed to authenticated and registered applications (or you can say authenticated users) and the rest are for any others.
Solution
So let's start.
Step 1
Open the Visual Studio 2012.
"File" -> "New" -> "Project...".
Then chose "Web" under "Templates" depending on your familiar language, C# or VB.Net. I will choose C#.
Then set the name of the application and click OK.
Then select the "Web API" and "Razor" in the view engine.
Step 2
Now in the next step we need to create a delegating handler that will help to process the authenticated the request.
Right-click on the project then select "Add" -> "Class" then name it "ApplicationAuthenticationHandler.cs".
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- namespace MonsterApiInc
- {
- public class ApplicationAuthenticationHandler
- {
- }
- }

Then override the method "SendAsync".
- public class ApplicationAuthenticationHandler : DelegatingHandler
- {
- protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
- {
- // Write your Authentication code here
- return base.SendAsync(request, cancellationToken);
- }
- }
So I will write the following code to authenticate the application:
- public class ApplicationAuthenticationHandler : DelegatingHandler
- {
- // Http Response Messages
- private const string InvalidToken = "Invalid Authorization-Token";
- private const string MissingToken = "Missing Authorization-Token";
- protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
- {
- // Write your Authentication code here
- IEnumerable<string> monsterApiKeyHeaderValues = null;
- // Checking the Header values
- if (request.Headers.TryGetValues("X-MonsterAppApiKey", out monsterApiKeyHeaderValues))
- {
- string[] apiKeyHeaderValue = monsterApiKeyHeaderValues.First().Split(':');
- // Validating header value must have both APP ID & APP key
- if (apiKeyHeaderValue.Length == 2)
- {
- // Code logic after authenciate the application.
- var appID = apiKeyHeaderValue[0];
- var AppKey = apiKeyHeaderValue[1];
- if (appID.Equals("MosterIPhoneX123") && AppKey.Equals("ThisMonsterIsPersist"))
- {
- var userNameClaim = new Claim(ClaimTypes.Name, appID);
- var identity = new ClaimsIdentity(new[] { userNameClaim }, "MonsterAppApiKey");
- var principal = new ClaimsPrincipal(identity);
- Thread.CurrentPrincipal = principal;
- if (System.Web.HttpContext.Current != null)
- {
- System.Web.HttpContext.Current.User = principal;
- }
- }
- else
- {
- // Web request cancel reason APP key is NULL
- return requestCancel(request, cancellationToken, InvalidToken);
- }
- }
- else
- {
- // Web request cancel reason missing APP key or APP ID
- return requestCancel(request, cancellationToken, MissingToken);
- }
- }
- else
- {
- // Web request cancel reason APP key missing all parameters
- return requestCancel(request, cancellationToken, MissingToken);
- }
- return base.SendAsync(request, cancellationToken);
- }
- private System.Threading.Tasks.Task<HttpResponseMessage> requestCancel(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken, string message)
- {
- CancellationTokenSource _tokenSource = new CancellationTokenSource();
- cancellationToken = _tokenSource.Token;
- _tokenSource.Cancel();
- HttpResponseMessage response = new HttpResponseMessage();
- response = request.CreateResponse(HttpStatusCode.BadRequest);
- response.Content = new StringContent(message);
- return base.SendAsync(request, cancellationToken).ContinueWith(task =>
- {
- return response;
- });
- }
- }
Step 3
Now to register the delegating handler.
Open the Global.asax file and provide one highlighted line of code.
- public class WebApiApplication : System.Web.HttpApplication
- {
- protected void Application_Start()
- {
- AreaRegistration.RegisterAllAreas();
- WebApiConfig.Register(GlobalConfiguration.Configuration);
- FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
- RouteConfig.RegisterRoutes(RouteTable.Routes);
- BundleConfig.RegisterBundles(BundleTable.Bundles);
- GlobalConfiguration.Configuration.MessageHandlers.Add(new
- ApplicationAuthenticationHandler());
- }
- }
Step 4
Make the resources authorized for the authenticated application (or users).
[Authorize]
Authorizing the attribute helps to make the resource available only for authorized applications and users.
Put "[Authorize]" before the method.
- [Authorize]
- public IEnumerable<string> Get()
- {
- return new string[] { "MonsterValue1", "MonsterValue2" };
- }
If the method does not have "[Authorize]" then it can be used by anonymous request.
Or we can use the "[AllowAnonymous]" attribute for anonymous requests.
- namespace MonsterApiInc.Controllers
- {
- public class ValuesController : ApiController
- {
- // GET api/values
- [Authorize]
- public IEnumerable<string> Get()
- {
- return new string[] { "MonsterValue1", "MonsterValue2" };
- }
- // GET api/values/5
- public string Get(int id)
- {
- return "MonsterValue";
- }
- // POST api/values
- public void Post([FromBody]string value)
- {
- }
- // PUT api/values/5
- public void Put(int id, [FromBody]string value)
- {
- }
- // DELETE api/values/5
- public void Delete(int id)
- {
- }
- }
- }
Now it's testing time.
Open the Fiddler Tool.
Download Fiddler here.
Build and run the project.
Then open Fiddler and supply the WebAPI resource URL and click "Execute" without header value (AppID and App Key) .
Because we have not supplied the application authentication token we get the Bad Request response that we have set when no header is found.
- // Web request cancel reason APP key missing all parameters
- return requestCancel(request, cancellationToken, MissingToken);
- private System.Threading.Tasks.Task<HttpResponseMessage> requestCancel(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken, string message)
- {
- CancellationTokenSource _tokenSource = new CancellationTokenSource();
- cancellationToken = _tokenSource.Token;
- _tokenSource.Cancel();
- HttpResponseMessage response = new HttpResponseMessage();
- response = request.CreateResponse(HttpStatusCode.BadRequest);
- response.Content = new StringContent(message);
- return base.SendAsync(request, cancellationToken).ContinueWith(task =>
- {
- return response;
- });
- }

Now let's the valid authentication token 
Then Execute and you will the response.
Go to the left pane and select the response.
Now we can get the response.
If you have any questions then please post the question here, I will try to provide a quick response.
Enjoy !!!

Shubham MittalPosted Aug 3, 2019, 12:46 PM
HI, I implemented it at my system but there is one issue at my end. There is no effect of including [Authorize] attribute. If i want to check this auth only for Particular method and User What's better way?
Sateesh MauryaPosted Jan 15, 2019, 3:59 AM
How to get body data on server
Sateesh MauryaPosted Jan 15, 2019, 3:59 AM
How to find body data
Riya MahantyPosted Jun 15, 2018, 9:19 AM
Its work fine but how i pass correct authentication from ajax http call
Anil SinghPosted Aug 3, 2015, 8:39 AM
It might help you.MVC Web API 2 Authorization and Authentication http://goo.gl/525Nq3
jeet singhPosted Jul 15, 2015, 8:01 AM
please let me know the claim in this its class
Former memberPosted Mar 18, 2015, 9:14 AM
Where and How to pass the valid authentication token in this example after bad request error?
Ian LeePosted Oct 14, 2013, 6:51 PM
Hi, I'm trying to implement this but I'm having a problem. It tries to authenticate regardless of whether I include the [Authorize], [AllowAnonymous] or no attribute at all. What am I doing wrong?