What is Authentication?
Authentication
is the process by which we check whether a user is allowed to access the
application. For this we match the passed credentials in our database and if the credentials do
not match, we restrict the user to access the application.
What is Token-Based Authentication?
Here we
are using token based authentication to validate user in our angular application
by passing the credentials to Asp.Net Web API. Web API validate the credentials
and if validated then return a valid access
token with expiration time. Angular application store this access token
locally in sessionStorage or localStorage. For subsequent request user
no need to provide the credentials again and this access token can be used to validate user till the token is valid.
Let’s
create an ASP.Net Web API first.
Open
Visual Studio and Create New project using File=>New=>Project…
Select
ASP.NET Web Application(.Net Framework) from Installed Web templates. Enter a
name for the project “TokenAuthWebAPI” and click OK button.
Select Web
API from project template. Click Change Authentication button and click OK
button.
Select
Individual User Accounts option and click OK.
It will take some time to create project with selected template. Below is
the application structure created automatically by Visual Studio.
Here in
the Providers folder visual studio has created a ApplicationOAuthProvider class
which validate the user from Microsoft Identity tables. When we apply [Authorize] attribute on any controller or action, Visual Studio create identity tables in App_Data folder. If we set our database name in DefaultConnection in connectionStrings section in web.config file, it creates those tables in our database. But we mostly
require to validate user from our own user table in our database. To do that we need to override this functionality by creating our own custom Authentication provider to validate user from our user table.
So, add a
class CustomOAuthProvider that implements OAuthAuthorizationServerProvider
class.
We need to
override GrantResourceOwnerCredentials method of this class. Here, I have used hard coded
username & password to validate the user but we can write code to validate
user from our user table by passing these username and password obtained from context object to Stored Procedure.
CustomOAuthProvider.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
namespace TokenAuthWebAPI.Providers
{
public class CustomOAuthProvider :
OAuthAuthorizationServerProvider
{
public override async Task
GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext
context)
{
await Task.Run(() =>
{
string username = "pramod";
string password = "pramod@12345";
bool isValidUser = (context.UserName.ToLower() == username &&
context.Password == password) ? true : false;
if (isValidUser == false)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
List<Claim> claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, user.username)
};
ClaimsIdentity oAuthIdentity = new ClaimsIdentity(claims,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity
= new ClaimsIdentity(claims,
OAuthDefaults.AuthenticationType);
AuthenticationProperties
properties = CreateProperties(user.UserID);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity,
properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
});
}
public override Task
ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
if (context.ClientId == null)
{
context.Validated();
}
return Task.FromResult<object>(null);
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string>
property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
public static
AuthenticationProperties CreateProperties(string userName)
{
IDictionary<string, string> data = new
Dictionary<string, string>
{
{ "userName", userName }
};
return new
AuthenticationProperties(data);
}
}
}
In Startup.cs
file comment ConfigureAuth(app) in Configuration() method and write following
code. Here, we have used our CustomOAuthProvider class instance.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Security.OAuth;
using System.Web.Http;
using TokenAuthWebAPI.Providers;
[assembly: OwinStartup(typeof(TokenAuthWebAPI.Startup))]
namespace TokenAuthWebAPI
{
public partial class Startup
{
public void
Configuration(IAppBuilder app)
{
//ConfigureAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
var customOAuthProvider = new CustomOAuthProvider();
OAuthAuthorizationServerOptions
options = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan =
TimeSpan.FromDays(1),
Provider = customOAuthProvider
};
app.UseOAuthAuthorizationServer(options);
app.UseOAuthBearerAuthentication(new
OAuthBearerAuthenticationOptions());
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
}
}
}
Now run
the application
In Angular Application
In Angular Application
In angular
application create a service using angular-cli command
ng g
service authentication --spec=false –module=app
To send
http request to Web API, use HttpClient. I have injected HttpClient using
constructor. HttpClient is imported from @angular/common/http library.
HttpHeaders
class is used to create request headers. HttpHeaders is also imported
from @angular/common/http library as follows:
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { HttpClient, HttpHeaders } from '@angular/common/http'
In login
method I have called the post method of HttpClient and if the validation successful
at Web API the response will contain the access token, user name and access token
expiration time. We have stored user name and access token in localStorage.
This will be used to check whether the user is authenticate or not for
subsequent request.
Logout
method remove these values from localStorage.
Authentication.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthenticationService {
API_BaseURL: string = "http://localhost:21453";
constructor(private http: HttpClient) { }
login(username: string, password: string) {
let userData = "username=" + username + "&password=" + password + "&grant_type=password";
let reqHeaders = new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded', 'No-Auth': 'true'
});
return this.http.post<any>(this.API_BaseURL + "/token", userData, { headers: reqHeaders }).pipe(map(user => {
localStorage.setItem("accessToken", user.access_token);
localStorage.setItem("username", user.userName);
}));
}
logout() {
localStorage. removeItem ("accessToken);
localStorage. removeItem ("username);
localStorage. removeItem ("username);
}
}
I hope you find this post helpful. Please comment about this post and provide any suggestion for further posts.
Thanks
Thanks

No comments:
Post a Comment