Tuesday, September 24, 2019

Creating a News App Project with Angular 8 and Bootstrap

Hello everyone, in this tutorial we are going to create a news app with Angular 8 and Bootstrap. We will be consuming free edition of the The Guardian Developer API to fetch the news articles. We will be including pagination, search and category based news for the purpose of this tutorial.

Once we are done we will have an app looking something like this.
Creating a News App Project with Angular 8 and Bootstrap : Final App

Get the API-Key

Firstly we will have to register on developer portal of The Guardian in order to obtain the Api Key which is required to consume its resources. Head to their portal and click on Register Developer Key. Follow the steps and you will have your unique Api Key. Head over to their documentation page in order to know about the structure of the response object so that it is easy for you to understand once we start consuming these API's.

Setup Angular Project

Use Angular CLI to generate a new project named news-app. Once created install the latest version of Bootstrap and FontAwesome icons by referring the steps mentioned on the below links:


We will also be using ngx-pagination for implementing client side pagination on the news articles which are fetched. To add that to your project refer to the below link:

Create Components/Models/Services

Creating a News App Project with Angular 8 and Bootstrap - Project Setup

  • Create three components named dashboard, header and footer.
  • Create a folder named shared
  • Create a service named news inside the shared folder
  • Create a class named news.model inside the shared folder
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, PipeTransform } from '@angular/core';
import {FormsModule} from '@angular/forms'
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { NewsService } from './shared/news.service';
import {HttpClientModule} from '@angular/common/http';
import {NgxPaginationModule} from 'ngx-pagination';
import { pipe } from 'rxjs';
import { FooterComponent } from './footer/footer.component';

@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    DashboardComponent,
    FooterComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    HttpClientModule,
    NgxPaginationModule
    
  ],
  providers: [NewsService],
  bootstrap: [AppComponent]
})
export class AppModule { }

  • Register the news service as a provider in the app.module.ts class as above.
  • Also import the HttpClientModule, FormsModule here as we will be using these modules as well.

Consuming the API

Firstly, we will create the News Model which we will use to store the articles which are returned from the API. Although there are multiple fields in the api, we will be using only few of them to show a preview of the article.Copy the code below into your news.model.ts file


export class NewsModel {
public sectionId: string;
public webPublicationDate : Date;
public webTitle: string;
public webUrl : string;
public thumbnail : string
public trailText : string
}

Below is the snapshot of the default response of the API, but since we are also showing a thumbnail, we will be using a property called show-fields=all to get additional fields as well. You can know more about these additional fields and properties here. As mentioned above, make sure you have gone through the documentation to know the capabilities of the API so that you can modify you application as per it.
Creating a News App Project with Angular 8 and Bootstrap - Default API response

Add the following code to your news.service.ts file. Here we will be consuming the endpoints using Http and store the result after mapping it into NewsModel type of object.


import { Injectable } from '@angular/core';
import { NewsModel } from './news.model';
import { HttpClient, HttpClientModule, HttpParams } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';  
import { Observable } from 'rxjs';  

@Injectable({
  providedIn: 'root'
})
export class NewsService {
newsArticles : NewsModel[] = [];
temp:NewsModel = new NewsModel;

gaurApiKey = "add your api key here";
gaurUrl = "http://content.guardianapis.com/search?show-fields=all&page-size=20&api-key=";
gaurSectionUrl = "https://content.guardianapis.com/search?show-fields=all&page-size=20&q="

  constructor(private http:HttpClient) { }

  GetAllGaurdian()
  {
    return this.http.get(this.gaurUrl + this.gaurApiKey);
  }

  GetGaurdianSearchResult(section:string)
  {
    return this.http.get(this.gaurSectionUrl + section + "&api-key=" + this.gaurApiKey );
  }

 public CusotomMapper(item) : NewsModel{
          
    this.temp = new NewsModel;
      this.temp.thumbnail = item["fields"].thumbnail;
      this.temp.sectionId= item["sectionId"];
      this.temp.webPublicationDate = item["webPublicationDate"];
      this.temp.webTitle = item["webTitle"];
      this.temp.webUrl = item["webUrl"];
      this.temp.trailText = item["fields"].trailText;
      return this.temp;
  }
}

Firstly we create a newsArticles variable which is array of type NewsModel. We also create a temp variable called temp which we will be using to convert the response into our type.

We then have three variables to store api key, general endpoint url and the url to filter news based on search terms or categories. The query parameter "q" is used to pass on the search term, api-key to pass the unique key etc.

We then have two methods, GetAllGaurdian(), used to get all the news and GetGaurdianSearchResult() which is used to get news based on some search text or filter

We then have a method named custom mapper which takes in the response object and creates a NewsModel type of object based upon the fields which we are using in are app.

Note: Since the response has these fields in hierarchical structure hence we had to write this mapper.

Working on the Components

header.component.html

<nav class="navbar navbar-light bg-success navbar-expand-lg">
    <a class="navbar-brand mt-1" href="#">
        <i class="fa fa-newspaper-o fa-2x text-dark  d-inline-block align-top">
    </i> Ng News</a>
    <button class="navbar-toggler" data-toggle="collapse" data-target="#navbaritem" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
</button>

    <div class="collapse navbar-collapse" id="navbaritem">
        <ul class="navbar-nav mr-auto mt-2 mt-lg-0 lead">
            <li class="nav-item active ">
                <a class="nav-link" href="#" (click)="filterClicked($event)">World</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#" (click)="filterClicked($event)">India</a>
            </li>
            <li class="nav-item ">
                <a class="nav-link" href="#" (click)="filterClicked($event)">Tech</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#" (click)="filterClicked($event)">Sports</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#" (click)="filterClicked($event)">Business</a>
            </li>

        </ul>

        <form class="form-group d-flex ml-auto mb-0" #form="ngForm" (submit)="onSubmit(form)">
            <input type="text" class="form-control mr-2 align-self-center" required placeholder="Search" name="searchText" [ngModel]="searchText" value="">
            <button class="btn btn-outline-warning align-self-center" [disabled]="!form.valid" type="submit">Search</button>
        </form>
    </div>
</nav>

Here we design the navigation bar which contains few links to fetch news based on catgories and a search box as well.

Creating a News App Project with Angular 8 and Bootstrap - NavBar.png

We wont be handling any events in this components, hence all its events like the nav clicks and search are emitted to its parent i.e. app component.

header.component.ts

import { Component,  OnInit, Output, EventEmitter } from '@angular/core';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
  filterText : string;
@Output() search = new EventEmitter();
@Output() filterButton = new EventEmitter();

  constructor() { }

  ngOnInit() {
  }
  onSubmit(form : NgForm)
  {
    console.log(form);
    this.search.emit(form);
  }

  filterClicked($event)
  {
    this.filterText = $event.target.text;
    this.filterButton.emit(this.filterText);
  }
}

Here the form submit event i.e. raised on the Search button and the <a> click events are emitted using search and filterButtons emitter.

dashboard.component.html

<div class="container-fluid py-5 bg-light">
    <div class="row">
        <div class="col-md-4 col-lg-3 my-3 d-flex align-items-stretch" *ngFor="let item of newsService.newsArticles | paginate: { itemsPerPage: 8, currentPage: p }">
            <div class="card">
                <img [src]="item.thumbnail" alt="" class="card-img-top img-fluid img-thumbnail">
                <div class="card-body">
                    <div class="card-title text-capitalize">
                        <h5>{{item.webTitle}}</h5>
                    </div>
                    <p class="card-text">
                        {{ (item.trailText | slice:0:100 ) +'..' }}
                    </p>
                    <div class="d-flex justify-content-left mt-3">
                        <p class="badge badge-secondary mr-3">{{item.webPublicationDate | date}}</p>
                        <p class="badge badge-secondary ">{{item.sectionId}}</p>
                    </div>

                </div>
                <div class="card-footer bg-warning d-flex justify-content-end">

                    <a [href]="item.webUrl" class="btn btn-success" target="_blank">
                        <i class="fa fa-book mr-1"></i>Read More
                    </a>
                </div>
            </div>
        </div>
    </div>
    <pagination-controls class="text-center" (pageChange)="p = $event"></pagination-controls>
</div>

Dashboard is the main component in terms of UI as here we will have the bootstrap code to show the news articles using cards layout.

dashboard.component.ts

import { Component, OnInit } from '@angular/core';
import { NewsService } from '../shared/news.service';
import { NewsModel } from '../shared/news.model';
import { Form } from '@angular/forms';
import { Pipe, PipeTransform } from '@angular/core';
import { element } from 'protractor';
@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {

  articles : any;
  temp : NewsModel = new NewsModel;
  constructor(private newsService : NewsService) { }

  ngOnInit() {
      this.FetchHeadlines();
           }

  FetchHeadlines()
  {
     this.newsService.GetAllGaurdian()
        .subscribe((result) =>
        {
          this.articles = result;
                  this.articles.response.results.forEach(element => {
                       this.newsService.newsArticles.push(this.newsService.CusotomMapper(element));
          });
        }) 
  }
}

The dashboard component consumes the NewsService using dependency injection in the constructor to fetch all news posts once the app is first loaded.

The response from API is stored in a variable named result and then we store it in a local array variable named articles. Then this array is iterated through and each item in it is passed through the custom mapper we created in news service to generate an object of type NewsModel. Once generated this object is stored in the newsArticle array which is used throughout the application to display the news 

footer.component.html  (optional)

<footer class="footer bg-dark py-5">
    <div class="container">
        <div class="row">
            <div class="col text-center">
                <h1 class="display-5 text-uppercase text-light mb-0">
                    <strong>Ng-News</strong>
                </h1>
                <div class="title-underline bg-primary">
                </div>
                <p class="text-white lead font-italic my-2">Web App built with Angular 8, Bootstrap and Gaurdian API</p>
            </div>
        </div>
    </div>
</footer>

footer.component.ts

No changes are required in the footer component and the CLI generated code fragment work as expected.

app.component.html

<app-header (search)="searchNews($event)" (filterButton)="filterNews($event)"></app-header>
<app-dashboard></app-dashboard>
<app-footer></app-footer>

Events from the Header component are handled using the searchNews() and filterNews() functions defined here.

app.component.ts


import { Component } from '@angular/core';
import { Form } from '@angular/forms';
import { NewsService } from './shared/news.service';
import { NewsModel } from './shared/news.model';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'news-app';
  searchText = "";
  resultSet : any;

  constructor(private newsService : NewsService) { }

  searchNews($event){
   
     this.searchText = $event.form.controls["searchText"].value;

     this.newsService.GetGaurdianSearchResult(this.searchText)
     .subscribe((result) => {
        this.resultSet = result;
        this.newsService.newsArticles = [];
        this.resultSet.response.results.forEach(element => {
                console.log(this.newsService.CusotomMapper(element));
        
        this.newsService.newsArticles.push(this.newsService.CusotomMapper(element))
      })
  
    })
  }

  filterNews(text: string)
  {
    console.log(text);
  
    // this.newsService.GetSearchResult(text)
    this.newsService.GetGaurdianSearchResult(text)
    .subscribe((result) => {
      this.newsService.newsArticles = [];
      this.resultSet = result;
      this.resultSet.response.results.forEach(element => {
           this.newsService.newsArticles.push(this.newsService.CusotomMapper(element));
    })
  
  })

}
}

Here we have two separate function defined for better understanding as the same could be achieved through a single function itself. The searchNews() is called when the user enters a search term and clicks on Search button in the navigation bar. This function in turn calls the GetGaurdianSearchResult() function which returns result based on the search query.

Creating a News App Project with Angular 8 and Bootstrap - Event Emitter


The filterNews() function is called when the user clicks on any of the navigation links we had like India, Business etc. The event sends the inner text of that link which is passed onto the GetGaurdianSearchResult() function.

That it's, we have finished Creating a News App Project with Angular 8 and Bootstrap tutorial. If you have any trouble following the steps of the tutorial, you can compare it with the working source code uploaded here.

Thursday, September 12, 2019

JSON Web Token with ASP.NET Web API and Angular

What is Json Web Token (JWT)


JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. 

In simple terms, we use these tokens, to authenticate and authorize requests which are made over the internet and also to share information in forms of object typically known as Claims. You can know more in detail about Jwt on there official website.

In this article we are going to implement a simple login page in Angular, which will call an Web API endpoint to authenticate a user. If the provided credentials are authenticated, the server return a JWT token, which the client (i.e. Angular app in our case) uses for further requests involving secure transmission.

Firstly, we are going to implement the back end service which will generate the token for the first request and validate it for any further requests.

Note: I will provide a link to code base at the end of this article

Backend with Asp.Net Web API

Step 1: Create an empty Asp.Net Web API Project and add the following Nuget Packages:
  • Microsoft.AspNet.Cors
  • System.IdentityModel.Token.Jwt
  • Microsoft.Owin.Security.OAuth
  • Swashbuckle
Step 2: Create a new class named "Jwt_Authentication", which will act as the middle ware to generate the JWT token.


using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace AngularJwt_Api.Business
{
    public class Jwt_Authentication
    {
        private static string Secret = "ERMN05OPLoDvbTTa/QkqLNMI7cPLguaRyHzyg7n5qNBVjQmtBhz4SzYh4NBVCXi3KJHlSXKP+oi2+bXr6CUYTR==";
        public static string GenerateToken(string username)
        {

            DateTime issuedAt = DateTime.UtcNow;
            DateTime expires = DateTime.UtcNow.AddDays(7);


            var tokenHandler = new JwtSecurityTokenHandler();

            ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[]
            {
                 new Claim(ClaimTypes.Name, "UserName"),
                new Claim(ClaimTypes.Email,"user@yopmail.com"),
                new Claim("DisplayName", "User"),
                new Claim(ClaimTypes.Role, "admin")
            });

            var now = DateTime.UtcNow;
            var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(Secret));
            var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey,
                Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature);


            var token =
                (JwtSecurityToken)
                 tokenHandler.CreateJwtSecurityToken(issuer: "http://localhost:51888", audience: "http://localhost:400",
                    subject: claimsIdentity, notBefore: issuedAt, expires: expires, signingCredentials: signingCredentials);
            var tokenString = tokenHandler.WriteToken(token);

            return tokenString;
        }

    }
}

This method will be called, once the credentials have been verified and the token needs to generated in order to send back to the client. In the real world scenario, Claims will have the details of the logged in user, and the Issuer and Audience Url's will be of the server and client application.

(Note, these will be different for you based on the port on which you API and Angular project are hosted)

Step 3: Create a simple model class to store the incoming request from the client. I have created a class named LoginModel.cs having two string properties Username and Password.

Step 4: Now we will be create the Controller which will have the logic to implement the authentication and call the GenerateToken method we created above.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using AngularJwt_Api.Models;
using AngularJwt_Api.Business;
using System.Net.Http;
using System.Net;
using System.Text;
using System.Web.Http.Cors;

namespace AngularJwt_Api.Controllers
{
 
    [EnableCors("*","*","*")]
    public class LoginController : ApiController
    {
        [HttpPost]
        [AllowAnonymous]
        public IHttpActionResult Authenticate([FromBody]LoginModel login)
        {
            bool isUsernamePasswordValid = false;

            if (login != null)
                isUsernamePasswordValid = login.Password == "admin" ? true : false;

            if (isUsernamePasswordValid)
            {
                string token = Jwt_Authentication.GenerateToken(login.Username);
             
                return Ok<string>(token);
            }
            else
            {
                return BadRequest("Login failed, invalid Username or Password.");
            }
        }

        [AuthorizeJwt]
        [HttpGet]
        public HttpResponseMessage GetSecureValues()
        {
            return this.Request.CreateResponse(HttpStatusCode.OK,
                        new { content = "Secure Content Returned" });
        }
    }
}

Here, we have two API endpoint, one which authenticates the user and the other which we will discuss later. The Authenticate method receives the LoginModel from the client and first the credentials are verified. For now we are simply matching the password but practically here we will make a call to the DB and get the credentials verified.

If the user is authenticated, the GenerateToken class is called with Username as parameter which is used in claims. You should pass on the actual User object to generate the claims.

Do remember to EnableCors in your project otherwise your angular application will not be able to communicate with the Api application.

We are all set to test are token generation logic through swagger. If you have not used Swagger before, it is a useful tool which generates documentation for your endpoints and gives you an interface to test them. It can be easily added to the project using Swashbuckle and then be accessed using /Swagger in the url of your application


Swagger to Generate Json Web Token in Asp.Net Web API


In the second image, we can see that our API return the JWT token in the Response Body. We will now move on to implementing the validation logic for incoming requests with these token.

Step 5: Create a new class names "AuthorizeJwtAttribute.cs". We will use this class to implement a custom Authorize Attribute to monitor, fetch, decode and validate the token.


using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;

namespace AngularJwt_Api.Business
{
    public class AuthorizeJwtAttribute : AuthorizeAttribute
    {
        private static string Secret = "ERMN05OPLoDvbTTa/QkqLNMI7cPLguaRyHzyg7n5qNBVjQmtBhz4SzYh4NBVCXi3KJHlSXKP+oi2+bXr6CUYTR==";
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            string token;
            if (!TryRetrieveToken(actionContext.Request, out token))
            {
                actionContext.Response =
                                     new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
            }

            try
            {
                var now = DateTime.UtcNow;
                var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(Secret));


                SecurityToken securityToken;
                JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
                TokenValidationParameters validationParameters = new TokenValidationParameters()
                {
                    ValidAudience = "http://localhost:50191",
                    ValidIssuer = "http://localhost:50191",
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    LifetimeValidator = this.LifetimeValidator,
                    IssuerSigningKey = securityKey
                };
                //extract and assign the user of the jwt
                Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
                HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);
                base.OnAuthorization(actionContext);

            }
            catch (SecurityTokenValidationException e)
            {
                actionContext.Response =
                                     new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
            }
            catch (Exception ex)
            {
                actionContext.Response =
                                      new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);
            }


        }


        private static bool TryRetrieveToken(HttpRequestMessage request, out string token)
        {
            token = null;
            IEnumerable<string> authzHeaders;
            if (!request.Headers.TryGetValues("Authorization", out authzHeaders) || authzHeaders.Count() > 1)
            {
                return false;
            }
            var bearerToken = authzHeaders.ElementAt(0);
            token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
            return true;
        }


        public bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
        {
            if (expires != null)
            {
                if (DateTime.UtcNow < expires)
                {
                    return true;
                }
            }
            return false;
        }
    }
}

Here in this class, we first retrive the token using the common Secret which we used while creating the token as well. Then we provide the parameters and use the inbuilt functions to validate the token.

LifetimeValidator function is implemented to check the expiry of our token. We have implemented it to be for 7 days but in real time it is somewhere around 20 mins to 30 mins in most of the applications.

We will now utilize the GetSecureValues function to use the custom attribute just created to limit the endpoint to bearer of our Jwt token.

Json Web Token in Asp.Net Web API implemented

test the endpoint for our token through Postman, move over to the Auth tab and select the Bearer Token from the Type dropdown. Enter the token and click on Send button.

So, our API is working as expected. We have now generated and validated a Json Web Token in our Web Api project.

Client Application with Angular

Step 6: We will now create a client application using Angular 8 in Visual Studio Code and consume our API. Follow the image below and create two components login-app and nav-bar, a model named login-model and a service to communicate to our Api named login-service.

Note: You can ignore nav-bar component and all other html code and create a simple form as long as it can take a username and password as input from the user.


Angular project structure to implement Json Web Tokens

login-model.ts


export class LoginModel {
  public  Username:string = "";
 public   Password:string = "";
}

login-app.component.ts

Here we will create a reactive form in angular to take in Username and Password from the users and on click of Submit button call the service class to communicate with the API. We have also implemented basic validation messages in the form.

The console.log method will help us showcase the values we entered and response we get back from the service once we complete the implementation.

Finally we will store the token returned in either browser local storage or session storage. One stored it will be available in the memory from where it can be fetched and added in headers for all further requests.

import { LoginServiceService } from './../login-service.service';
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators, FormControl} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import { LoginModel } from '../login-model';


@Component({
  selector: 'app-login-app',
  templateUrl: './login-app.component.html',
  styleUrls: ['./login-app.component.css']
})
export class LoginAppComponent implements OnInit {

  loginForm : FormGroup;
  loginmodel : LoginModel = new LoginModel();
  
  constructor(
    private formBuilder : FormBuilder,
    private loginService : LoginServiceService
  
  ) { }

  ngOnInit() {
    this.loginForm = this.formBuilder.group(
      {
        username : ['',Validators.required],
        password : ['',Validators.required]
      }
    );
  }

  get(key:string) : string
  {
    return this.loginForm.controls[key].value;
  }

  onSubmit() : void{
    console.log(this.loginForm.value);
    console.log(this.get('username'));
    console.log(this.get('password'));

   
    this.loginmodel.Username = this.get('username');
    this.loginmodel.Password = this.get('password');
    
    this.loginService.AuthenticateUser(this.loginmodel)
        .subscribe((response) => {
            console.log(response);
            localStorage.setItem('token', response.toString());
            sessionStorage.setItem('token', response.toString());
        })

  }

}

login-app.component.html

Basic Angular form created using Bootstrap. We have also used a simple Angular Material button for the Submit, but in case you have not worked with them before it is easier and faster to work with default bootstrap buttons for the purpose of this article.

<div class="card col-md-4 login-div offset-md-4">
      
    <h5 class="card-header">Login into the App!</h5>
   <div class="form-div card-body">
    <form [formGroup] = "loginForm" (ngSubmit) = "onSubmit($event)">
        <div class="form-group">
            <input type="text" formControlName= "username" class = "form-control" placeholder="UserName">
            <div class="error has-error alert-danger errorDiv" *ngIf = "loginForm.controls['username'].errors
            && loginForm.controls['username'].touched">
                               
                <div>Username is required</div>
            </div>
         </div>
         <div class="form-group">
            <input type="text" formControlName= "password" class = form-control placeholder="Password">
            <div class="error has-error alert-danger errorDiv" *ngIf = "loginForm.controls['password'].errors
            && loginForm.controls['password'].touched">
                <div>Password is required</div>
            </div>
         </div>
         <div>
         <button mat-raised-button color = 'primary' type="submit">  
            Login
        </button>
            <span style="float: right; margin-top: 12px">Forgot Password</span>
        </div>
    </form>
   </div>
  
</div>

nav-bar.component.ts (Optional )


import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-nav-bar',
  templateUrl: './nav-bar.component.html',
  styleUrls: ['./nav-bar.component.css']
})
export class NavBarComponent implements OnInit {

isLoggedIn: boolean

  constructor() { }

  ngOnInit() {
    this.isLoggedIn = false;
  }

}

nav-bar.component.html (Optional )


<nav class="navbar navbar-expand-lg navbar-light" style="background-color: #ffc048">
        <a class="navbar-brand" href="#">Angular Jwt App</a>
       
        <div class="collapse navbar-collapse navList" style="overflow: hidden;">
          <ul class="navbar-nav">
            <li class="nav-item" *ngIf = "!isLoggedIn">
              <a class="nav-link" href="#">Login</a>
            </li>
            <li class="nav-item" *ngIf = "isLoggedIn">
             <a class="nav-link" href="#">Hello</a>
            </li>

            <li class="nav-item mr-auto ml-2 mt-lg-0" style="margin-left: 2%">
              <a class="nav-link" href="#">Logout</a>
            </li>
        </ul>
        
        </div>
      </nav>

    

login-service.service.ts

Here we use the HttpClient module in Angular to call the method in our Api which returns the token if the user is authenticated. This method is subscribed in the login-app.component.ts

import { LoginModel } from './login-model';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
//import {Response, RequestOptions, Headers } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';  
import { Observable } from 'rxjs';  

@Injectable({
  providedIn: 'root'
})
export class LoginServiceService {

  base_url = "http://localhost:51888/api";
  loginModel : LoginModel;
  constructor(private http: HttpClient) { }

  AuthenticateUser(login : LoginModel){
   
    return this.http.post(this.base_url + "/Login",login)
  }

}

app.module.ts


import { LoginServiceService } from './custom-components/login-service.service';
import { LoginModel } from './custom-components/login-model';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
//import { HttpModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginAppComponent } from './custom-components/login-app/login-app.component';
import { NgForm, FormsModule, ReactiveFormsModule } from '@angular/forms';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatButtonModule} from '@angular/material/button';
import {MatIconModule} from '@angular/material/icon';
import { NavBarComponent } from './custom-components/nav-bar/nav-bar.component';
import { HttpClientModule } from '@angular/common/http';


@NgModule({
  declarations: [
    AppComponent,
    LoginAppComponent,
    NavBarComponent,
    
      ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    ReactiveFormsModule,
    BrowserAnimationsModule,
    MatButtonModule,
    MatIconModule,
    HttpClientModule   
  ],
  providers: [LoginModel, LoginServiceService],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html


<app-nav-bar></app-nav-bar>

<app-login-app></app-login-app>

No changes are required in the app.component.ts file.

Angular App to implement Json Web Token with Asp.Net Web Api

We can now use the dummy credentials we have hard coded in our Api to test if our client app work and if the token is saved in the cookie and local storage of the browser

Json Web Token returned from Asp.Net Web Api in Angular

Json Web Token stored in browser storage

Summary

In this article we have successfully implemented Json Web Token based authentication in Asp.Net Web Api using an Angular application as a client. It is the basic skeleton above which you can build any enterprise level application.


Note: To install the Angular dependencies, open the project in VS Code and run "npm install" followed by "ng serve"