Angular 11 JWT Authentication Example With Web API - BezKoder

Download as pdf or txt
Download as pdf or txt
You are on page 1of 33
At a glance
Powered by AI
The key takeaways from the document are that it discusses building an Angular application with JWT authentication, including components like registration, login, and protected routes.

The main components of the Angular application discussed are services, components, routing and http interceptors.

Authentication works by having a user register or login, which returns a JWT that is then used to make requests and check authorization on protected routes based on the user's role.

bezkoder.

com

Angular 11 JWT Authentication


example with Web Api - BezKoder
bezkoder
26-33 minutes

In this tutorial, we’re gonna build an Angular 11 Token based


Authentication & Authorization with Web Api Application (including
HttpInterceptor, Router & Form Validation) that implements
JWT Authentication. I will show you:
JWT Authentication Flow for User Signup & User Login
Project Structure for Angular 11 Authentication with
HttpInterceptor, Router
How to implement HttpInterceptor
Creating Login, Signup Components with Form Validation
Angular Components for accessing protected Resources
How to add a dynamic Navigation Bar to Angular App
Working with Browser Session Storage
Let’s explore together.
Related Posts:
– In-depth Introduction to JWT-JSON Web Token
– Angular 11 CRUD Application example with Web API
– Angular 11 File upload example with Progress bar
Fullstack:
– Angular + Spring Boot: JWT Authentication & Authorization
example
– Angular + Node.js Express: JWT Authentication & Authorization
example
Contents [hide]
Overview of Angular 11 JWT Authentication example
Flow for User Registration and User Login
Angular App Diagram with Router and HttpInterceptor
Technology
Setup Angular 11 Project
Project Structure
Setup App Module
Create Services
Authentication Service
Token Storage Service
Data Service
Http Interceptor
Add Bootstrap to Angular project
Create Components for Authentication
Register Component
Login Component
Profile Component
Create Role-based Components
Public Component
Protected Components
App Routing Module
App Component
Run the Angular App
Source Code
Conclusion
Further Reading
We will build an Angular 11 JWT Authentication & Authorization
application with Web Api in that:
There are Register, Login pages.
Form data will be validated by front-end before being sent to back-
end.
Depending on User’s roles (admin, moderator, user), Navigation
Bar changes its items automatically.
Services contain methods for sending HTTP requests & receiving
reponses
Here are the screenshots of our app:
– Signup Page:

– Form Validation:
– Login Page:

– Profile Page:

– Navigation Bar for Admin account:


Demo

This is full Angular JWT Authentication App (including form


validation, check signup username/email duplicates, test
authorization for 3 roles: Admin, Moderator, User) with Spring Boot
Server:
In the video, we use Spring Boot for back-end REST APIs. You can
find explanation and source code at:
– Spring Boot JWT Authentication with Spring Security & MySQL
– Spring Boot JWT Authentication with Spring Security &
PostgreSQL
– Spring Boot JWT Authentication with Spring Security & MongoDB
Logic is the same if you use following Node.js Express back-end:
– Node.js + MySQL: JWT Authentication & Authorization example
– Node.js + PostgreSQL: JWT Authentication & Authorization
example
– Node.js + MongoDB: User Authentication & Authorization with
JWT

Flow for User Registration and User Login

For JWT – Token based Authentication with Web API, we’re gonna
call 2 endpoints:
POST api/auth/signup for User Registration
POST api/auth/signin for User Login
You can take a look at following flow to have an overview of
Requests and Responses that Angular 11 Client will make or
receive.

Angular Client must add a JWT to HTTP Authorization Header


before sending request to protected resources. This can be done
by using HttpInterceptor.

Angular App Diagram with Router and


HttpInterceptor

Now look at the diagram below.

– The App component is a container using Router. It gets user


token & user information from Browser Session Storage via
token-storage.service. Then the navbar now can display
based on the user login state & roles.
– Login & Register components have form for submission data
(with support of Form Validation). They use token-
storage.service for checking state and auth.service for
sending signin/signup requests.
– auth.service uses Angular HttpClient ($http service) to
make authentication requests.
– every HTTP request by $http service will be inspected and
transformed before being sent by auth-interceptor.
– Home component is public for all visitor.
– Profile component get user data from Session Storage.
– BoardUser, BoardModerator, BoardAdmin components will
be displayed depending on roles from Session Storage. In these
components, we use user.service to get protected resources
from API.

Technology

– Angular 11
– RxJS 6
– Angular CLI 11

Setup Angular 11 Project

Let’s open cmd and use Angular CLI to create a new Angular
Project as following command:
ng new Angular10JwtAuth
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use?
CSS
We also need to generate some Components and Services:
ng g s _services/auth
ng g s _services/token-storage
ng g s _services/user

ng g c login
ng g c register
ng g c home
ng g c profile
ng g c board-admin
ng g c board-moderator
ng g c board-user
After the previous process is done, under src folder, let’s create
_helpers folder and auth.interceptor.ts file inside.
Now you can see that our project directory structure looks like this.

Project Structure

Setup App Module

Open app.module.ts, then import FormsModule &


HttpClientModule.
We also need to add authInterceptorProviders in
providers. I will show you how to define it later on this tutorial (in
auth.interceptor.ts).
import { BrowserModule } from '@angular/platform-
browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common
/http';

import { AppRoutingModule } from './app-


routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login
/login.component';
import { RegisterComponent } from './register
/register.component';
import { HomeComponent } from './home
/home.component';
import { ProfileComponent } from './profile
/profile.component';
import { BoardAdminComponent } from './board-
admin/board-admin.component';
import { BoardModeratorComponent } from './board-
moderator/board-moderator.component';
import { BoardUserComponent } from './board-
user/board-user.component';

import { authInterceptorProviders } from


'./_helpers/auth.interceptor';

@NgModule({
declarations: [
AppComponent,
LoginComponent,
RegisterComponent,
HomeComponent,
ProfileComponent,
BoardAdminComponent,
BoardModeratorComponent,
BoardUserComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule
],
providers: [authInterceptorProviders],
bootstrap: [AppComponent]
})
export class AppModule { }

Create Services

Authentication Service

This service sends signup, login HTTP POST requests to back-end.


_services/auth.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from
'@angular/common/http';
import { Observable } from 'rxjs';

const AUTH_API = 'http://localhost:8080/api/auth


/';

const httpOptions = {
headers: new HttpHeaders({ 'Content-Type':
'application/json' })
};

@Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(private http: HttpClient) { }

login(username: string, password: string):


Observable<any> {
return this.http.post(AUTH_API + 'signin', {
username,
password
}, httpOptions);
}

register(username: string, email: string,


password: string): Observable<any> {
return this.http.post(AUTH_API + 'signup', {
username,
email,
password
}, httpOptions);
}
}

Token Storage Service

TokenStorageService to manages token and user information


(username, email, roles) inside Browser’s Session Storage. For
Logout, we only need to clear this Session Storage.
_services/token-storage.service.ts
import { Injectable } from '@angular/core';

const TOKEN_KEY = 'auth-token';


const USER_KEY = 'auth-user';

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

signOut(): void {
window.sessionStorage.clear();
}

public saveToken(token: string): void {


window.sessionStorage.removeItem(TOKEN_KEY);
window.sessionStorage.setItem(TOKEN_KEY,
token);
}

public getToken(): string | null {


return
window.sessionStorage.getItem(TOKEN_KEY);
}

public saveUser(user: any): void {


window.sessionStorage.removeItem(USER_KEY);
window.sessionStorage.setItem(USER_KEY,
JSON.stringify(user));
}

public getUser(): any {


const user =
window.sessionStorage.getItem(USER_KEY);
if (user) {
return JSON.parse(user);
}

return {};
}
}

Data Service

This service provides methods to access public and protected


resources.
_services/user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

const API_URL = 'http://localhost:8080/api/test/';

@Injectable({
providedIn: 'root'
})
export class UserService {
constructor(private http: HttpClient) { }

getPublicContent(): Observable<any> {
return this.http.get(API_URL + 'all', {
responseType: 'text' });
}

getUserBoard(): Observable<any> {
return this.http.get(API_URL + 'user', {
responseType: 'text' });
}

getModeratorBoard(): Observable<any> {
return this.http.get(API_URL + 'mod', {
responseType: 'text' });
}

getAdminBoard(): Observable<any> {
return this.http.get(API_URL + 'admin', {
responseType: 'text' });
}
}
You can see that it’s simple because we have HttpInterceptor.

Http Interceptor

HttpInterceptor has intercept() method to inspect and transform


HTTP requests before they are sent to server.
AuthInterceptor implements HttpInterceptor. We’re gonna
add Authorization header with ‘Bearer’ prefix to the token.
_helpers/auth.interceptor.ts
import { HTTP_INTERCEPTORS, HttpEvent } from
'@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest
} from '@angular/common/http';

import { TokenStorageService } from '../_services


/token-storage.service';
import { Observable } from 'rxjs';
const TOKEN_HEADER_KEY = 'Authorization'; //
for Spring Boot back-end

@Injectable()
export class AuthInterceptor implements
HttpInterceptor {
constructor(private token: TokenStorageService)
{ }

intercept(req: HttpRequest<any>, next:


HttpHandler): Observable<HttpEvent<any>> {
let authReq = req;
const token = this.token.getToken();
if (token != null) {
authReq = req.clone({ headers:
req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' +
token) });
}
return next.handle(authReq);
}
}

export const authInterceptorProviders = [


{ provide: HTTP_INTERCEPTORS, useClass:
AuthInterceptor, multi: true }
];
intercept() gets HTTPRequest object, change it and forward to
HttpHandler object’s handle() method. It transforms
HTTPRequest object into an Observable<HttpEvents>.
next: HttpHandler object represents the next interceptor in
the chain of interceptors. The final ‘next’ in the chain is the Angular
HttpClient.
This client will work well with the back-end in the posts:
– Spring Boot JWT Authentication with Spring Security & MySQL
– Spring Boot JWT Authentication with Spring Security &
PostgreSQL
– Spring Boot JWT Authentication with Spring Security & MongoDB

Note: If you use this front-end app for Node.js Express back-end in
one of these tutorials:
– Node.js + MySQL: JWT Authentication & Authorization
– Node.js + PostgreSQL: JWT Authentication & Authorization
– Node.js + MongoDB: User Authentication & Authorization with
JWT
Please use x-access-token header like this:
...
const TOKEN_HEADER_KEY = 'x-access-token';

@Injectable()
export class AuthInterceptor implements
HttpInterceptor {
...
intercept(req: HttpRequest, next: HttpHandler):
Observable<HttpEvent<any>> {
...
if (token != null) {
authReq = req.clone({ headers:
req.headers.set(TOKEN_HEADER_KEY, token) });
}
return next.handle(authReq);
}
}
...

Add Bootstrap to Angular project

Open index.html and import Bootstrap inside <head /> tag.


<!DOCTYPE html>
<html lang="en">
<head>
...
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com
/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-
Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh
crossorigin="anonymous"
/>
</head>
<body>
<app-root></app-root>
</body>
</html>

Create Components for Authentication

Register Component

This component binds form data (username, email, password)


from template to AuthService.register() method that returns
an Observable object.
register/register.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../_services
/auth.service';

@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
form: any = {
username: null,
email: null,
password: null
};
isSuccessful = false;
isSignUpFailed = false;
errorMessage = '';
constructor(private authService: AuthService) {
}

ngOnInit(): void {
}

onSubmit(): void {
const { username, email, password } =
this.form;

this.authService.register(username, email,
password).subscribe(
data => {
console.log(data);
this.isSuccessful = true;
this.isSignUpFailed = false;
},
err => {
this.errorMessage = err.error.message;
this.isSignUpFailed = true;
}
);
}
}
We use Form Validation in the template:
username: required, minLength=3, maxLength=20
email: required, email format
password: required, minLength=6
register/register.component.html
<div class="col-md-12">
<div class="card card-container">
<img
id="profile-img"
src="//ssl.gstatic.com/accounts
/ui/avatar_2x.png"
class="profile-img-card"
/>
<form
*ngIf="!isSuccessful"
name="form"
(ngSubmit)="f.form.valid && onSubmit()"
#f="ngForm"
novalidate
>
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
class="form-control"
name="username"
[(ngModel)]="form.username"
required
minlength="3"
maxlength="20"
#username="ngModel"
/>
<div class="alert-danger"
*ngIf="username.errors && f.submitted">
<div
*ngIf="username.errors.required">Username is
required</div>
<div *ngIf="username.errors.minlength">
Username must be at least 3 characters
</div>
<div *ngIf="username.errors.maxlength">
Username must be at most 20 characters
</div>
</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input
type="email"
class="form-control"
name="email"
[(ngModel)]="form.email"
required
email
#email="ngModel"
/>
<div class="alert-danger"
*ngIf="email.errors && f.submitted">
<div *ngIf="email.errors.required">Email
is required</div>
<div *ngIf="email.errors.email">
Email must be a valid email address
</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
class="form-control"
name="password"
[(ngModel)]="form.password"
required
minlength="6"
#password="ngModel"
/>
<div class="alert-danger"
*ngIf="password.errors && f.submitted">
<div
*ngIf="password.errors.required">Password is
required</div>
<div *ngIf="password.errors.minlength">
Password must be at least 6 characters
</div>
</div>
</div>
<div class="form-group">
<button class="btn btn-primary btn-
block">Sign Up</button>
</div>

<div class="alert alert-warning"


*ngIf="f.submitted && isSignUpFailed">
Signup failed!<br />{{ errorMessage }}
</div>
</form>

<div class="alert alert-success"


*ngIf="isSuccessful">
Your registration is successful!
</div>
</div>
</div>

Login Component

Login Component also uses AuthService to work with


Observable object. Besides that, it calls
TokenStorageService methods to check loggedIn status and
save Token, User info to Session Storage.
login/login.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../_services
/auth.service';
import { TokenStorageService } from '../_services
/token-storage.service';

@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
form: any = {
username: null,
password: null
};
isLoggedIn = false;
isLoginFailed = false;
errorMessage = '';
roles: string[] = [];

constructor(private authService: AuthService,


private tokenStorage: TokenStorageService) { }

ngOnInit(): void {
if (this.tokenStorage.getToken()) {
this.isLoggedIn = true;
this.roles =
this.tokenStorage.getUser().roles;
}
}

onSubmit(): void {
const { username, password } = this.form;

this.authService.login(username,
password).subscribe(
data => {

this.tokenStorage.saveToken(data.accessToken);
this.tokenStorage.saveUser(data);

this.isLoginFailed = false;
this.isLoggedIn = true;
this.roles =
this.tokenStorage.getUser().roles;
this.reloadPage();
},
err => {
this.errorMessage = err.error.message;
this.isLoginFailed = true;
}
);
}

reloadPage(): void {
window.location.reload();
}
}
Here are what we validate in the form:
username: required
password: required, minLength=6
login/login.component.html
<div class="col-md-12">
<div class="card card-container">
<img
id="profile-img"
src="//ssl.gstatic.com/accounts
/ui/avatar_2x.png"
class="profile-img-card"
/>
<form
*ngIf="!isLoggedIn"
name="form"
(ngSubmit)="f.form.valid && onSubmit()"
#f="ngForm"
novalidate
>
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
class="form-control"
name="username"
[(ngModel)]="form.username"
required
#username="ngModel"
/>
<div
class="alert alert-danger"
role="alert"
*ngIf="username.errors && f.submitted"
>
Username is required!
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
class="form-control"
name="password"
[(ngModel)]="form.password"
required
minlength="6"
#password="ngModel"
/>
<div
class="alert alert-danger"
role="alert"
*ngIf="password.errors && f.submitted"
>
<div
*ngIf="password.errors.required">Password is
required</div>
<div *ngIf="password.errors.minlength">
Password must be at least 6 characters
</div>
</div>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block">
Login
</button>
</div>
<div class="form-group">
<div
class="alert alert-danger"
role="alert"
*ngIf="f.submitted && isLoginFailed"
>
Login failed: {{ errorMessage }}
</div>
</div>
</form>

<div class="alert alert-success"


*ngIf="isLoggedIn">
Logged in as {{ roles }}.
</div>
</div>
</div>

Profile Component

This Component gets current User from Storage using


TokenStorageService and show information (username, token,
email, roles).
profile/profile.component.ts
import { Component, OnInit } from '@angular/core';
import { TokenStorageService } from '../_services
/token-storage.service';

@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
currentUser: any;

constructor(private token: TokenStorageService)


{ }

ngOnInit(): void {
this.currentUser = this.token.getUser();
}
}
profile/profile.component.html
<div class="container" *ngIf="currentUser; else
loggedOut">
<header class="jumbotron">
<h3>
<strong>{{ currentUser.username }}</strong>
Profile
</h3>
</header>
<p>
<strong>Token:</strong>
{{ currentUser.accessToken.substring(0, 20) }}
...
{{
currentUser.accessToken.substr(currentUser.accessToken.length
- 20) }}
</p>
<p>
<strong>Email:</strong>
{{ currentUser.email }}
</p>
<strong>Roles:</strong>
<ul>
<li *ngFor="let role of currentUser.roles">
{{ role }}
</li>
</ul>
</div>

<ng-template #loggedOut>
Please login.
</ng-template>

Create Role-based Components


Public Component

Our Home Component will use UserService to get public


resources from back-end.
home/home.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../_services
/user.service';

@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
content?: string;

constructor(private userService: UserService) {


}

ngOnInit(): void {
this.userService.getPublicContent().subscribe(
data => {
this.content = data;
},
err => {
this.content =
JSON.parse(err.error).message;
}
);
}
}
home/home.component.html
<div class="container">
<header class="jumbotron">
<p>{{ content }}</p>
</header>
</div>

Protected Components

These Components are role-based. But authorization will be


processed by back-end.
We only need to call UserService methods:
getUserBoard()
getModeratorBoard()
getAdminBoard()
Here is an example for BoardAdminComponent.
BoardModeratorComponent & BoardUserComponent are
similar.
board-admin/board-admin.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../_services
/user.service';

@Component({
selector: 'app-board-admin',
templateUrl: './board-admin.component.html',
styleUrls: ['./board-admin.component.css']
})
export class BoardAdminComponent implements OnInit
{
content?: string;

constructor(private userService: UserService) {


}

ngOnInit(): void {
this.userService.getAdminBoard().subscribe(
data => {
this.content = data;
},
err => {
this.content =
JSON.parse(err.error).message;
}
);
}
}
board-admin/board-admin.component.html
<div class="container">
<header class="jumbotron">
<p>{{ content }}</p>
</header>
</div>

App Routing Module

We configure the Routing for our Angular app in app-


routing.module.ts.
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from
'@angular/router';

import { RegisterComponent } from './register


/register.component';
import { LoginComponent } from './login
/login.component';
import { HomeComponent } from './home
/home.component';
import { ProfileComponent } from './profile
/profile.component';
import { BoardUserComponent } from './board-
user/board-user.component';
import { BoardModeratorComponent } from './board-
moderator/board-moderator.component';
import { BoardAdminComponent } from './board-
admin/board-admin.component';

const routes: Routes = [


{ path: 'home', component: HomeComponent },
{ path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent
},
{ path: 'profile', component: ProfileComponent
},
{ path: 'user', component: BoardUserComponent },
{ path: 'mod', component:
BoardModeratorComponent },
{ path: 'admin', component: BoardAdminComponent
},
{ path: '', redirectTo: 'home', pathMatch:
'full' }
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Routes array is passed to the RouterModule.forRoot()
method.
We’re gonna use <router-outlet></router-outlet>
directive in the App Component where contains navbar and display
Components (corresponding to routes) content.

App Component

This component is the root Component of our Angular application, it


defines the root tag: <app-root></app-root> that we use in
index.html.
app.component.ts
import { Component, OnInit } from '@angular/core';
import { TokenStorageService } from './_services
/token-storage.service';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private roles: string[] = [];
isLoggedIn = false;
showAdminBoard = false;
showModeratorBoard = false;
username?: string;

constructor(private tokenStorageService:
TokenStorageService) { }

ngOnInit(): void {
this.isLoggedIn =
!!this.tokenStorageService.getToken();

if (this.isLoggedIn) {
const user =
this.tokenStorageService.getUser();
this.roles = user.roles;

this.showAdminBoard =
this.roles.includes('ROLE_ADMIN');
this.showModeratorBoard =
this.roles.includes('ROLE_MODERATOR');

this.username = user.username;
}
}

logout(): void {
this.tokenStorageService.signOut();
window.location.reload();
}
}
First, we check isLoggedIn status using
TokenStorageService, if it is true, we get user’s roles and set
value for showAdminBoard & showModeratorBoard flag. They
will control how template navbar displays its items.
The App Component template also has a Logout button link that
call logout() method and reload the window.
app.component.html
<div id="app">
<nav class="navbar navbar-expand navbar-dark bg-
dark">
<a href="#" class="navbar-brand">bezKoder</a>
<ul class="navbar-nav mr-auto"
routerLinkActive="active">
<li class="nav-item">
<a href="/home" class="nav-link"
routerLink="home">Home </a>
</li>
<li class="nav-item" *ngIf="showAdminBoard">
<a href="/admin" class="nav-link"
routerLink="admin">Admin Board</a>
</li>
<li class="nav-item"
*ngIf="showModeratorBoard">
<a href="/mod" class="nav-link"
routerLink="mod">Moderator Board</a>
</li>
<li class="nav-item">
<a href="/user" class="nav-link"
*ngIf="isLoggedIn" routerLink="user">User</a>
</li>
</ul>

<ul class="navbar-nav ml-auto"


*ngIf="!isLoggedIn">
<li class="nav-item">
<a href="/register" class="nav-link"
routerLink="register">Sign Up</a>
</li>
<li class="nav-item">
<a href="/login" class="nav-link"
routerLink="login">Login</a>
</li>
</ul>

<ul class="navbar-nav ml-auto"


*ngIf="isLoggedIn">
<li class="nav-item">
<a href="/profile" class="nav-link"
routerLink="profile">{{ username }}</a>
</li>
<li class="nav-item">
<a href class="nav-link"
(click)="logout()">LogOut</a>
</li>
</ul>
</nav>

<div class="container">
<router-outlet></router-outlet>
</div>
</div>

Run the Angular App

You can run this App with command: ng serve.


This client will work well with the back-end in the posts:
– Spring Boot JWT Authentication with Spring Security & MySQL
– Spring Boot JWT Authentication with Spring Security &
PostgreSQL
– Spring Boot JWT Authentication with Spring Security & MongoDB
If you use this front-end app for Node.js Express back-end in one of
these tutorials:
– Node.js + MySQL: JWT Authentication & Authorization
– Node.js + PostgreSQL: JWT Authentication & Authorization
– Node.js + MongoDB: User Authentication & Authorization with
JWT
It configures CORS for port 8081, so you have to run command: ng
serve --port 8081 instead.

Conclusion

Today we’ve done so many things from setup Angular 11 Project to


write Services and Components for Token based Authentication
with Web Api. I hope you understand the overall layers of our
Angular application, and apply it in your project at ease. Now you
can build a front-end app that supports JWT Authentication &
Authorization with Angular 11, HttpInterceptor and Router.
For other Angular versions, please visit:
– Angular 8 JWT Authentication example
– Angular 10 JWT Authentication example
Happy learning, see you again!

Further Reading

Angular 11 CRUD Application example with Web API


Angular 11 File upload example with Progress bar
Angular Pagination example | ngx-pagination

Source Code

You can find the complete source code for this tutorial on Github.

You might also like