Wednesday 22 January 2020

How to secure ASP.NET Web API using Token Based Authentication

Whenever we work on enterprise-level application either application based on web or windows platform the first biggest concern comes in our mind is its security. When the requirement is to expose our business services to the client then securing those services is on top priority. Just because we’ve built a WEB API that we want to make it public, it doesn’t mean that we allow anybody accessing it and consuming our services without any proper validation. Nowadays adoption of WEB API is increasing at the expeditious pace so it is highly recommended for the developer to implement security for all types of clients trying to consume WEB API. In this article, we will learn how to secure ASP.NET Web API using token-based authentication.
Securing WEB API

What is Token Based Authentication :

Let us take an example to understand what actually is Token Based Authentication? Whenever we visit local street food shop or in a restaurant, we have to pay money for Token to get specific foods and then when we take the token to counter we get food after validating that particular token. As nowadays almost every web company using WEB API, tokens are the best way to handle authentication for multiple users.
The whole process goes through a few steps. First, we allow users to provide the required credential like username and password which accessing a service. When the user provides a valid username and password, a token will be issued to a user which allow them to consume WEB API to get resources.secure ASP.NET Web API

Implementation – Secure ASP.NET Web API:

Let’s learn how we can Implement WEB API token-based authentication in our application. Simply follow given steps one by one.
Step 1: Create a WEB API Application
  • Open Visual Studio
  • Go to the File menu
  • Create > Projet
  • Select Web
  • Select “asp.net web application”
  • Enter application name
  • Select your project location
  • Click on the add button
It will bring up a new dialog window for select template > here I will select empty template > and then checked MVC & Web API checkbox from Add folder and core references for > and then click on the Ok button.
Step 2: Add following NuGet package from NuGet package manager
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security.OAuth
  • Microsoft.Owin.Cors
(We can install through Package Manager Console
Go to View->Other windows -> Package Manager Console
Install-Package Microsoft.Owin.Host.SystemWeb -Version 2.1.0
Install-Package Microsoft.Owin.Security.OAuth -Version 2.1.0
Install-Package Microsoft.Owin.Cors -Version 2.1.0
)
Step 3: Create a class named “AuthorizationServerProvider” you can change this name. The same name is not mandatory. Write given code
public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
if (context.UserName == "user" && context.Password == "password")
{
identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
identity.AddClaim(new Claim("username", "user"));
identity.AddClaim(new Claim(ClaimTypes.Name, "RaviRanjanKr"));
context.Validated(identity);
}
else
{
context.SetError("invalid_grant", "Wrong credentials Used. Please Try again");
return;
}
}
}
In this “AuthorizationServerProvider” class we can see that AuthorizationServerProvider” is inheriting  “OAuthAuthorizationServerProvider” in order to override two required function “ValidateClientAuthentication” and “GrantResourceOwnerCredentials”
You might be thinking about why we are overriding these two methods and what actual difference is.
ValidateClientAuthentication must be used to make sure that the client is valid and have rights to consume resources. We do this perhaps if we have already registered the client to an authorization server and now need to verify that it is a confidential client and is still valid.
GrantResourceOwnerCredentials is used when we expect to accept required credentials like an actual username and password and issue an access token after verifying given credential by the client.
Step 4 : Create another class naming “AuthorizeAttribute” and write given the code
public class AuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(actionContext);
}
else
{
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
}
}
}
In this class, we can see “AuthorizeAttribute” class is inheriting “AuthorizeAttribute” class reside in System.Web.Http namespace. Here we are overriding HandleUnauthorizedRequest function residing in AuthorizeAttribute class. AuthorizeAttribute.HandleUnauthorizedRequest Method (HttpActionContext) basically processes requests that fail authorization.
Step 5: Once you created both required class, now create another class named “Startup” and write given the code
[assembly: OwinStartup(typeof(WEBAPITokenBasedAuth.Startup))]
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
//enable cors origin requests
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
var myProvider = new AuthorizationServerProvider();
OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = myProvider
};
app.UseOAuthAuthorizationServer(options);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
}
}
view rawOwinStartup.cs hosted with ❤ by GitHub
Here we will add OWIN Startup which would help us to configure the OAuth Authorization Server.
[su_note]Don’t forget to use [assembly: OwinStartup(typeof(WEBAPITokenBasedAuth.Startup))] above class “Startp”[/su_note]
To know more about OWIN Startup class and its configuration, Navigate owin-startup-class-detection
Step 6: Now go to App_Start and do some changes in “WebApiConfig” class. If you don’t have this class in your project then simply create one with the same name in App_Start. Write given code in “WebApiConfig” class
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Step 7: Make sure below one line is written In Global.asax.cs under “Application_Start” function of a Global class. If not, please write it.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register); // you have to define Register function of WebApiConfig class
}
}
Step 8: Now create a WEB API controller. The controller should(not must) be in the Controller folder. Write given code in Controller
public class DataController : ApiController
{
public string Connection
{
get
{
return ConfigurationManager.ConnectionStrings["con"].ConnectionString;
}
}
[Authorize]
[HttpGet]
[Route("api/data/authenticate")]
public DataSet GetAuthenticate()
{
var identity = (ClaimsIdentity)User.Identity;
if (identity.Name == "RaviRanjanKr")
{
DataSet dsRecord = new DataSet();
try
{
using (SqlConnection myConnection = new SqlConnection(Connection))
{
using (SqlCommand myCommand = new SqlCommand("procFixFD", myConnection))
{
myCommand.CommandType = CommandType.StoredProcedure;
using (SqlDataAdapter da = new SqlDataAdapter(myCommand))
{
da.Fill(dsRecord);
}
}
}
}
catch (Exception)
{ }
if (dsRecord.Tables[0].Rows.Count > 0)
{
return dsRecord;
}
else
{
return null;
}
}
else
{
return null;
}
}
view rawDataController.cs hosted with ❤ by GitHub
Great. Now you have created your WEB API with token-based authentication. You can use WEB API testing tools like fiddler or postman. Don’t worry we will guide you on how to check. Here we are going to learn how to consume WEB API using postman. Follow the given steps
Step 1: You have to enter a few details before you post details on the server.
  • Select type POST
  • Enter URL of WEB API with “/token” like “http://localhost:port/token”
  • Enter credential in Body.
  • Click on the Send button.
secure ASP.NET Web API using token based authentication
Step 2: When you click on the Send button, you’ll get the auto-generated token.
Step 3: Once you get a token, again you have to follow some step to authenticate generated token.
  • Select Type – GET
  • Enter WEB API URL with “/authenticate” in Params like “http://localhost:port/api/data/authenticate”
  • Enter Authorization for Key under Header and for Value, you have to enter “Bearer generated-token…”
  • Click on the Send button
secure ASP.NET Web API using token based authentication
Step 4: After clicking on the send button we will see Status: 200 OK. Means we are successfully done with token-based authentication. The token you sent back to the server is now authenticated and consumed data is on Screen.
You can download complete source code from here –
[su_button url=”https://github.com/raviranjankr/WEBAPITokenBasedAuth” target=”blank” style=”3d” background=”#7a1d18″ size=”5″ radius=”round”]Download Source Code [/su_button]
If you have any query to understand things or having any problem while implementing token-based authentication, feel free to write in the comment box.

No comments:

Post a Comment

Baisic Useful Git Commands

  Pushing a fresh repository Create a fresh repository(Any cloud repository). Open terminal (for mac ) and command (windows) and type the be...