Introduction
In this article, we will perform authentication using Web API, Entity Framework, and Angular 7 web applications. We are using the SQL database as the back-end with Entity Framework. In the middle layer, we will use Web API for data connectivity between the database and the front-end application. On the UI side, we will use an Angular 7 application.
We are using SQL Server for the database, Visual Studio for the Web API, and Visual Studio Code for creating the Angular application.
Step 1 Create a Database Table and Stored Procedure
Open SQL Server and create a database table as in the below code. After the table is created successfully, insert some user data for authentication and create one stored procedure. If you have already had this type of table, you can skip this step.
-
-
- CREATE TABLE [dbo].[UserLogin](
- [Id] [int] IDENTITY(1,1) NOT NULL,
- [UserName] [varchar](50) NULL,
- [UserPassword] [varchar](50) NULL,
- [UserEmail] [varchar](50) NULL,
- [UserRole] [varchar](50) NULL,
- CONSTRAINT [PK_UserLogin] PRIMARY KEY CLUSTERED
- (
- [Id] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
-
- GO
-
-
-
-
- insert into UserLogin(UserName,UserPassword,UserEmail,UserRole)
- values ('admin','123456','[email protected]','admin')
-
-
- Create PROCEDURE [dbo].[EF_UserLogin]
- @UserName varchar(50)=null,
- @UserPassword varchar(50)=null
- AS
- BEGIN
-
- SET NOCOUNT ON;
-
- SELECT UserName,UserPassword,UserEmail,UserRole from UserLogin where UserName=@UserName and UserPassword=@UserPassword
- END
Step 2 - Create a New Web API Project
Now, open Visual Studio, create a Web API project as you see in the below image. Here, select the "No Authentication" option because we don't want to use a membership database.
Open Visual Studio >> File >> New >> Poject >> Select Web API.
Click OK.
Step 3 - Install Required Packages
Now, find NuGet Package Manager, click on "Install". You can also use the Package Manager Console. In the Package Manager Console window, type the following command. After installation, these packages will be available in references.
Install-Package
name of the package
- Microsoft.Owin.Host.SystemWeb
- Microsoft.Owin.Security.OAuth
- Microsoft.Owin.Cors
Here, we also need to install a package for enabling CORS. This dependency is used for allowing our origin (domain) of the front-end on the Web API.
Microsoft.AspNet.WebApi.Cors
Step 4 - Now, Add ASO.NET Entity Data Model
Now, we are creating a new ADO.NET Entity Data Model. Select the stored procedure for checking the user login credentials, as you see in the given image.
Step 5 - Create a Startup.cs Class File
Here, we need to create a new class file to implement the code configuration provider and create an instance of class MyAuthProvider.
- using Microsoft.Owin;
- using Microsoft.Owin.Security.OAuth;
- using Owin;
- using System;
- using System.Web;
- using System.Web.Http;
-
- [assembly: OwinStartup(typeof(TokenBaseAuthentication.Startup))]
- namespace TokenBaseAuthentication
- {
- public class Startup
- {
-
- public void Configuration(IAppBuilder app)
- {
-
- app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
-
- var myProvider = new MyAuthProvider();
- OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
- {
- AllowInsecureHttp = true,
- TokenEndpointPath = new PathString("/token"),
- AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
- Provider = myProvider
- };
- app.UseOAuthAuthorizationServer(options);
- app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
-
-
- HttpConfiguration config = new HttpConfiguration();
- WebApiConfig.Register(config);
- }
-
- }
- }
Step 6 - Create MyAuthProvider.cs Class File
Now, let us create one more class to implement OAuthAuthorizationServerProvider and call our ADO.NET Entity Model. This model validates the user from a database.
- using Microsoft.Owin.Security.OAuth;
- using System.Linq;
- using System.Security.Claims;
- using System.Threading.Tasks;
- using System.Web;
-
- namespace TokenBaseAuthentication
- {
- public class MyAuthProvider : OAuthAuthorizationServerProvider
- {
-
- public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
- {
- context.Validated();
- }
-
- public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
- {
- var identity = new ClaimsIdentity(context.Options.AuthenticationType);
-
- UserEntities obj = new UserEntities();
- var userdata = obj.EF_UserLogin(context.UserName, context.Password).FirstOrDefault();
- if (userdata != null)
- {
- identity.AddClaim(new Claim(ClaimTypes.Role, userdata.UserRole));
- identity.AddClaim(new Claim(ClaimTypes.Name, userdata.UserName));
- context.Validated(identity);
- }
- else
- {
- context.SetError("invalid_grant", "Provided username and password is incorrect");
- context.Rejected();
- }
- }
-
- }
-
- }
Open the Web API config file and add this code.
Now, we are done with almost all the required code for Web API application.
Step 7 - Create New Angular Project
Now, we are creating a new Angular application for UI. Here, I am using VS Code IDE for front-end; you can use any IDE for creating the Angular application. Given below is the command for Angular application creation. One thing to keep in mind before Angular installation is that you have already installed Node and AngularCLI in your system.
ng new TokenBaseAuth
Step 8 - Create New Service in Angular
Now, we are creating a new service for calling the Web API. As you can see, here, we are defining the API URL for sending a request to the server.
ng generate service myservice
- import { Injectable } from '@angular/core';
- import { HttpClient , HttpHeaders,HttpParams } from '@angular/common/http';
-
- @Injectable({
- providedIn: 'root'
- })
- export class MyserviceService {
-
- constructor(private http: HttpClient) { }
-
-
- postData(data): any {
- const body = new HttpParams()
- .set('grant_type', data.grant_type)
- .set('username', data.username)
- .set('password', data.password)
- return this.http.post('http://localhost:64793/token', body.toString(), {observe: 'response',
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
- });
- }
- }
Step 9 - Create New login Component
Now, let us create a login component using the following command and write the given code in that component.
ng generate component login
- // login.component.ts code
- import { Component, OnInit } from '@angular/core';
- import { FormGroup, FormControl, Validators } from '@angular/forms';
- import { MyserviceService } from '../myservice.service'
- @Component({
- selector: 'app-login',
- templateUrl: './login.component.html',
- styleUrls: ['./login.component.css']
- })
- export class LoginComponent implements OnInit {
- form: FormGroup;
- successmsg: any;
- errmsg: any;
- constructor(private Userservice : MyserviceService) { }
- ngOnInit() {
- this.form = new FormGroup({
- username: new FormControl('', [Validators.required]),
- password: new FormControl('', [Validators.required, Validators.minLength(6)]),
- grant_type: new FormControl('password'),
- });
- }
-
-
- onSubmit()
- {
- this.Userservice.postData(this.form.value)
- .subscribe(res => {
- if (res.status === 200) {
- this.successmsg = 'token - ' + res.body.access_token; localStorage.setItem('access_token', res.body.access_token);
- } else {
- this.errmsg = res.status + ' - ' + res.statusText;
- }
- },
- err => {
- if (err.status === 401 ) {
- this.errmsg = 'Invalid username or password.';
- }
- else if (err.status === 400 ) {
- this.errmsg = 'Invalid username or password.';
- }
- else {
- this.errmsg ="Invalid username or password";
- }
- });
- }
- }
Open the login.component.html file and write the code given below.
- <div class="container">
- <div class="row">
-
- <div class="col-md-4"></div>
- <div class="col-md-4 jumbotron">
- <h3>Login</h3><hr>
- <form [formGroup]="form" (ngSubmit)="onSubmit()" novalidate>
- <div class="form-group">
- <label for="uname">User Name:</label>
- <div class="input-group">
- <div class="input-group-addon glyphicon glyphicon-user"></div>
- <input type="text" placeholder="username" formControlName="username" maxlength="20" class="form-control">
- </div>
- <div class="alert alert-danger" *ngIf="form.controls['username'].dirty && form.controls['username'].invalid">
- <div *ngIf="form.controls['username'].hasError('required')">Username is required</div>
- </div>
- </div>
-
- <div class="form-group">
- <label for="pwd">Password:</label>
- <div class="input-group">
- <div class="input-group-addon glyphicon glyphicon-lock"></div>
- <input type="password" placeholder="password" formControlName="password" class="form-control">
- </div>
- <div class="alert alert-danger" *ngIf="form.controls['password'].dirty && form.controls['password'].invalid">
- <div *ngIf="form.controls['password'].hasError('required')">Password is required</div>
- <div *ngIf="form.controls['password'].hasError('minlength')">Password must minlength 6 characters long.</div>
- </div>
- </div>
- <div class="form-group">
- <input type="submit" value="Login" class="btn btn-primary" [disabled]="form.invalid" >
- </div>
- <div class="form-group">
- <div class="col-md-12 alert alert-danger" *ngIf="errmsg">{{errmsg}}</div>
- </div>
-
- <div class="form-group">
- <div class="col-md-12 alert alert-success" *ngIf="successmsg">{{successmsg}}</div>
- </div>
-
- </form>
- </div>
- </div>
- </div>
In HTML templete, we are using bootstrap for styling. So, let us install bootstrap now using the below command and import the style.css file.
npm install bootstrap@4 --save
-
- @import "~bootstrap/dist/css/bootstrap.css";
Step 10 - Open app.module.ts File
Now, open the app.module.ts file. We need to import the service and required modules like Form module, HTTPClient module etc. For that, we can use the following code.
- import { BrowserModule } from '@angular/platform-browser';
- import { NgModule } from '@angular/core';
-
- import { AppComponent } from './app.component';
- import { LoginComponent } from './login/login.component';
-
-
- import {FormsModule,ReactiveFormsModule } from '@angular/forms'
- import {MyserviceService} from './myservice.service'
- import { HttpClientModule } from '@angular/common/http';
-
-
-
- @NgModule({
- declarations: [
- AppComponent,
- LoginComponent
- ],
- imports: [
- BrowserModule,
- FormsModule,
- ReactiveFormsModule ,
- HttpClientModule
- ],
- providers: [MyserviceService],
- bootstrap: [AppComponent]
- })
- export class AppModule { }
Open the app.component.html file and write the given below code for rendering the login HTML templete.
We are almost done with the login component, module, and service code.
Step 11 - Run Application
Now, let us run both the applications - Web API and Agular application.
ng serve -o
After compiling successfully, you will see the output like in the below image. The port number here is 4200 that is our Web API application port.
Here, we are receiving a token as a response. We are passing this bearer token with the header in the HTTP request or we can also pass it with HTTP interceptor and validate on the server-side controller level or action level, as you can see in the below code snippet.
- [Authorize]
- public class MyController : ApiController
- {
-
- }
Summary
I have attached the .rar files of this demonstration. This file does not hold the packages folder, Web API, and node module folder. You can download the source code. For Angular application, use the below command for installing the package.
npm install
In this article, we learned the implementation of token-based authentication using Web API, Entity Framework, and Angular 7. Thank you for reading this article.