In this tutorial, we’re gonna build an Angular 8 Token based Authentication 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 8 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
It sounds fantastic! Let’s explore together.
Related Post: In-depth Introduction to JWT-JSON Web Token
Newer versions:
– Angular 10
– Angular 11
– Angular 12
– Angular 13.
– Angular 14
Fullstack:
– Angular 8 + Spring Boot: JWT Authentication with Spring Security example
– Node.js Express + Angular 8: JWT Authentication & Authorization example
– MEAN stack Authentication: Login & Registration with Angular 8 example
Contents
- Overview of Angular 8 JWT Authentication example
- Flow for User Registration and User Login
- Angular App Diagram with Router and HttpInterceptor
- Technology
- Setup Angular 8 Project
- Project Structure
- Setup App Module
- Create Services
- Http Interceptor
- Add Bootstrap to Angular project
- Create Components for Authentication
- Create Role-based Components
- App Routing Module
- App Component
- Run the Angular App
- Source Code
- Conclusion
- Further Reading
Overview of Angular 8 JWT Authentication example
We will build an Angular 8 Token based Authentication 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
Screenshots
– Signup Page:
– Login Page:
– Profile Page:
– Navigation Bar for Admin account:
You can implement Refresh Token with following post:
Angular 8 Refresh Token with Interceptor and JWT example
Demo
This is full Angular 8 JWT Authentication App (with form validation, check signup username/email duplicates, test authorization with 3 roles: Admin, Moderator, User).
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: User Authentication & Authorization example with JWT
– Node.js + PostgreSQL: User Authentication & Authorization with JWT
– 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 8 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 8
– RxJS 6
Setup Angular 8 Project
Let’s open cmd and use Angular CLI to create a new Angular Project as following command:
ng new Angular8JwtAuth
? 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.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';
import { HomeComponent } from './home/home.component';
import { BoardAdminComponent } from './board-admin/board-admin.component';
import { BoardUserComponent } from './board-user/board-user.component';
import { BoardModeratorComponent } from './board-moderator/board-moderator.component';
import { ProfileComponent } from './profile/profile.component';
import { authInterceptorProviders } from './_helpers/auth.interceptor';
@NgModule({
declarations: [
AppComponent,
LoginComponent,
RegisterComponent,
HomeComponent,
BoardAdminComponent,
BoardUserComponent,
BoardModeratorComponent,
ProfileComponent
],
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(credentials): Observable<any> {
return this.http.post(AUTH_API + 'signin', {
username: credentials.username,
password: credentials.password
}, httpOptions);
}
register(user): Observable<any> {
return this.http.post(AUTH_API + 'signup', {
username: user.username,
email: user.email,
password: user.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() {
window.sessionStorage.clear();
}
public saveToken(token: string) {
window.sessionStorage.removeItem(TOKEN_KEY);
window.sessionStorage.setItem(TOKEN_KEY, token);
}
public getToken(): string {
return sessionStorage.getItem(TOKEN_KEY);
}
public saveUser(user) {
window.sessionStorage.removeItem(USER_KEY);
window.sessionStorage.setItem(USER_KEY, JSON.stringify(user));
}
public getUser() {
return JSON.parse(sessionStorage.getItem(USER_KEY));
}
}
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 } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { TokenStorageService } from '../_services/token-storage.service';
const TOKEN_HEADER_KEY = 'Authorization';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private token: TokenStorageService) { }
intercept(req: HttpRequest<any>, next: HttpHandler) {
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 one of 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) {
...
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 = {};
isSuccessful = false;
isSignUpFailed = false;
errorMessage = '';
constructor(private authService: AuthService) { }
ngOnInit() {
}
onSubmit() {
this.authService.register(this.form).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=20email
: 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="f.submitted && username.invalid">
<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="f.submitted && email.invalid">
<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="f.submitted && password.invalid">
<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 = {};
isLoggedIn = false;
isLoginFailed = false;
errorMessage = '';
roles: string[] = [];
constructor(private authService: AuthService, private tokenStorage: TokenStorageService) { }
ngOnInit() {
if (this.tokenStorage.getToken()) {
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
}
}
onSubmit() {
this.authService.login(this.form).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() {
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="f.submitted && username.invalid"
>
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="f.submitted && password.invalid"
>
<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() {
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() {
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 = '';
constructor(private userService: UserService) { }
ngOnInit() {
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() {
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() {
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 8 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 with Angular 8, HttpInterceptor and Router.
You can also find newer versions at the posts:
– Angular 10 JWT Authentication example with Web Api
– Angular 11 JWT Authentication example with Web Api
– Angular 12 JWT Authentication example with Web Api
– Angular 13 JWT Authentication example with Web Api.
– Angular 14 JWT Authentication example with Web Api
Happy learning, see you again!
Further Reading
Source Code
You can find the complete source code for this tutorial on Github.
You can implement Refresh Token with following post:
Angular 8 Refresh Token with Interceptor and JWT example
Thanks!
Thanks!
Good tutorial! Keep up the nice work.
Hello, i have a problem if someone can help me,
in the back-end i have this error : Error: Role is not found.
because in the front-end we don’t specify the roles, for a simple user where i must add the role on the html singup form? or in ts file?
for admin/moderator i added it manually but for a simple user how to do that from front-end form?
This Angular tutorial is awesome! Thanks!
Hi bezkoder,
Thanks in advance for sharing your knowledge! Your tutorials are great.
I got an error with angular front end part.(Spring boot backend works without any problem through postman).
The error is it doesn’t load any part of UI.instead of that it comesup with this error.(I’m using angular 8)
Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.
at new PathLocationStrategy (common.js:782)
at Object.provideLocationStrategy [as useFactory] (router.js:9875)
at Object.factory (core.js:17376)
at R3Injector.hydrate (core.js:17206)
…………
What should I update
Hi bezkoder,
I am not able to login successfully, there is no error come, when I saw in console network there is 204 status code return,
please provide solution ,
Hi,
Yes, I have tested it with port 8081 without success
OPTIONShttp://localhost:8080/api/v1/employees
[HTTP/1.1 401 13ms]
Solicitud de origen cruzado bloqueada: La política de mismo origen (Same Origin Policy) no permite la lectura de recursos remotos en http://localhost:8080/api/v1/employees. (Motivo: La respuesta CORS no tuvo éxito).
Hi, I don’t know where ’employees’ is. Please follow step by step in my tutorial.
I am a beginner to angular and spring boot. Can any one please help me to understand how the role is assigned to any new user (admin/mod/user) while registeration.
register(user): Observable {
return this.http.post(AUTH_API + ‘signup’, {
username: user.username,
email: user.email,
password: user.password
}, httpOptions);
}
I didn’t found any roles array int the above code, how it is inserted.
Thank You in advance
Hi, it is inserted by default in backend.
If you want to set roles manually, you can add roles/role array in the Post request body.
Hi,
we need help with the CORS. We still can’t solve the problem. We still can’t solve the problem API calls
Hi, you can try to run the Angular App with command
ng serve --port 8081
first.i do the same your code at front end, but front end style is not the same like your images on Signup and Login. Mine were a wide range. Is there something wrong or not? can u guide me some?
Thank you for your code.
Hi, you can check .css files on Github source code, and don’t forget to import Bootstrap in index.html 🙂
Thank you, bez. I forgot to check the css file. using the styl file. Now it’s ok for front end.
hello and thank you for this tutorial
I have a problem,
property ‘getAdminBoard’ does not exist on type ‘AuthService’
and it’s the same message for ‘getUserBoard’ and ‘getModeratorBoard’ that’s what! do I have to declare this property in my service as constant?
Hello, Congratulations and thanks for sharing your work … But I have a problem. How could I make a post with the data of the logged in user ???? For example, id, name + other attributes of another table that user has a relationship ???
Thank u so much bro.!!
Thanks !!!! Great Tuto !!
when make a call between angular and spring boot http://localhost:8081/register
i got this error
In the controller side
@RestController @CrossOrigin(origins = “http://localhost:8081”)
and application.properties server.port=8080
In angular side
const API_URL = ‘http://localhost:8080/api/auth/’;
Access to XMLHttpRequest at ‘http://localhost:8080/api/auth/signup’ from origin ‘http://localhost:8081’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.
hi Bez,
Thank you very much for your great tutorial. Loved it so much and learned a lot.
However, I would like to mention that I somehow found a small problem in this line
this.tokenStorage.saveToken(data.accessToken);
for me the object data does not have a property called “accessToken”, but just “token”. That made the access to protected resources does not work at first.
Thanks again and have a nice day.
thx u so much, so clear and easy to understand.
Big love from france (f)
but i have one probleme, when i type :http://localhost:4200/user or http://localhost:4200/admin i have an error :
Error: Unauthorized even if i am logged with a correct name and password.
Perhaps i need to add Authorizarion to header but how?
thx
Hi, which backend server do you use? Spring Boot or Node.js?
You should follow the instruction for modifying
app/_helpers/auth.interceptor.js
.I need did it with MySQL and I’m having the same issue
I added a class to do CRUD, it works in the backend, when I authenticate I have the authorization to access, but in angularjs, it does not work maybe I have to add something in my code in angularjs
Hello, thank you for this excellent tutorial .
i have problems with the role based authentication, the angular signup form only reads the role(admin) passed in :
And i don’t know how to set the payload role as an array ca you help me with that please ?
Thnak you
Thank for your response.
****** auth.service.ts ******
Please post your controller code also 🙂
******auth.controller.js ******
Check your database, in roles collection/table. Did it have role object with name=client?
Role.findOne({ name: "client" }...)
If not, you should follow the step of creating 3 roles in database.
Yes i have a role object with name=client but the signup form in angular only read the client role even if i put admin role in the form ? I think i have to set the payload role is an array ? how can i fix it please ?
Yes, the payload should contain
role
as an array 🙂Hi, thank you so much for this tutorial. I followed this one and the one for node.js backend but i got this error :
TypeError: Cannot read property ‘_id’ of null
at C:\Users\LDE\pfe20\backend\controllers\auth.controller.js:56:28
Hi, please show your code here.
Hello Bezkoder,
thanks for your wonderful guides. I followed this one and the one for node.js backend and everything works great <3 !
Since i would call me a beginner, i have problems with the protected components. Can i send html from backend: user.controller.js , or do i need a different way to send html that works together with component.ts ?
Thank you in advance ! Greetings from Germany
Hi, if you use Node.js Express:
Or you can search google with keyword: server-side rendering.
Thank you very much for your help. I dont think, that server-side rendering fits my project. Any tips for protecting existing routes with the JWT provided by your tutorials without using html from the server ?
Thank you so much for your time !
So it should not add role in user constructor ?!!
Yes, you can, notice to set it as an array in the payload 🙂
Hello how can i set role as an array in the payload ?
Check this https://stackoverflow.com/questions/61470684/how-can-i-add-roles-using-angular
Hello! I try to add role in registration but it doesn’t work
Hi, make sure that you set the correct payload:
role
/roles
is an array.thanks very much for this tutorail but i got this error with angular “error TS2306: File auth.interceptor.ts’ is not a module”
i solved it i just refresh vscode
Hello! Thank you a lot for sharing this tutorial it is very helpful, I have a question which is I added roles to register form so I had this error :
Signup failed!
Invalid JSON input: Cannot deserialize instance of `java.util.HashSet` out of VALUE_STRING token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.HashSet` out of VALUE_STRING token at [Source: (PushbackInputStream); line: 1, column: 79] (through reference chain: com.suivi.app.Model.RegistrationForm[“roles”])
Even I didn’t add roles to the form, sign up failed and if you asking about register is it working on back end yeah it works. Please can you help me to solve this issue. And Than you.
Please notice that the array in HTTP request body is
role
, notroles
🙂Hello, how can i assign a specific role when registering ? thank you, i try to input a role in register form but the set type doesn’t accept a string
Hi, you need to transform the form data into JSON payload like this:
thank you, i have solved this problem already
how exactly did you solve this problem please?
This is awesome, so beautifully described, thanks a lot!
I finished this one and I’m working on adding canActivate() method so that it protects routes of admin and user.
If you have done any blog on it or know any sources please attach them on the reply.
Thanks a lot, you’re a life saver.
Excuse me, I already installed it from the console and not from the ide VS.
thanks anyway
Hi, when you download the project and run ng serve …
An unhandled exception occurred: Cannot find module ‘@angular/compiler-cli’
I have Angular 8.3.23.
I try npm install. but nothing, an error appears
npm WARN saveError ENOENT: no such file or directory,…….
Hi, you can try these steps:
– update angular-cli to the latest version
– update the project dependencies
hi, please if you explain me this:
thank you
Hi, the code tells the server that this client is sending JSON data.
Hi, I’ve tried to make some modification in the register.component.html (to add another field), but I cannot see any of them after I run “ng serve”. Do you have any idea what I am doing wrong?
Hi, please show your code here.
I just tried to display another field “check password” [I just copy/paste/change a little bit the code used for password…in html]
It is hard for me to check your issue while not seeing your code.
Bonjour,
j’ai obtient le problème suivant
Access to XMLHttpRequest at ‘http://localhost:8080/api/auth/signin’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.
Malgré que j’ai ajouté au niveau de l’api rest le code suivant;@CrossOrigin(origins = “http://localhost:4200” ,allowedHeaders = “*”,allowCredentials = “true”)
Quelqu’un peut m’aider?
Hi, the server you used configures CORS for port 8081, so you have to run this Angular client with command:
ng serve --port 8081
instead.Thanks a lot for sharing your knowledge.
Good job
I’m getting a CORS error from having my REST API on api.domain.com and my Angular site on dev.domain.com . How do I allow the CORS between subdomains?
Error:
Access to XMLHttpRequest at ‘http://api.domain.com/auth/signup’ from origin ‘http://dev.domain.com’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The ‘Access-Control-Allow-Origin’ header has a value ‘http://api.domain.com/’ that is not equal to the supplied origin.
Hi, you should configure CORS in your REST API for origin
dev.domain.com
🙂I managed to figure it out, I want to be able to accept preflight and origin from all my subdomain and main domain so I setup a multi origin configuration. Might be useful as an addition for the article. Attaching below the reference.
https://expressjs.com/en/resources/middleware/cors.html
Yeah, I’m happy to know that you fixed it 🙂
Hi,
Thanks a lot for the helpful and beautiful tutorial. i have one question, i didn’t figure out where we put our token when we send a request to get a protected ressource.
thank you.
Hi, we use Angular
HttpInterceptor
to add token to Header before sending Http requests 🙂Hi!
How do you assign roles to users?
Hi, you can find the way to assign roles to user in the post for backend in this tutorial (signup process)
Hey! I really got to understand all the explanation and followed step by step. But I have a problem everytime I try to Log In, maybe i missed something but i don’t really get the error. I get everytime “Signup failed!
Error: Role is not found.”
Thanks for the code! It’s very friendly for the ones that are starting with spring+angular.
I figured it out! I missed adding the roles! Thank u very much lots of love from Argentina <3
Yeah, you should add Roles before registration 🙂
Remarks To: Angular 8 JWT Authentication with HttpInterceptor and Router
It was nice to read your post. It is very organized and detailed. I did not actually implemented and run your code, (because lack of time these days…). But I liked very much your attitude to intercept all requests (e.g. clone token to all requests) as long as there is “live” token in the memory. leaving the handle of the role-based authorizations in the server side, and save all the headache of dealing with the “whitelist / blacklist” of routs. But of course this have to be managed properly in the server code
Thanks for this excellent material, it was usefull for me and it is really clearly and easy to understand with great explanation. Great job!
Thank you for your compliment which motivates me to write more better articles 🙂
Thanks! This Angular app works like a charm.