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
Newer versions:
– Angular 12 JWT Authentication example with Web Api
– Angular 13 JWT Authentication example with Web Api
– Angular 14 JWT Authentication example with Web Api
Contents
- 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
- 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 11 JWT Authentication example
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:
If you want to know more details about Form Validation, please visit:
Angular 11 Form Validation example (Reactive Forms)
– Login Page:
– Profile Page:
– Navigation Bar for Admin account:
You also need to implement Refresh Token, please visit:
Angular 11 JWT Refresh Token with Http Interceptor example
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 Angular11JwtAuth
? 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=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="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>
In the code above, we use Template Driven Form, you want to know more details about Reactive Form Validation, please visit:
Angular 11 Form Validation example (Reactive Forms)
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.
You also need to implement Refresh Token, please visit:
Angular 11 JWT Refresh Token with Http Interceptor example
For other Angular versions, please visit:
– Angular 8 JWT Authentication example
– Angular 10 JWT Authentication example
– Angular 12 JWT Authentication example
– Angular 13 JWT Authentication example
– Angular 14 JWT Authentication example
Happy learning, see you again!
Further Reading
- Angular 11 Form Validation example (Reactive Forms)
- Angular 11 CRUD Application example with Web API
- Angular 11 File upload example with Progress bar
- Angular Pagination example | ngx-pagination
Fullstack:
- Angular + Spring Boot: JWT Authentication & Authorization example
- Angular + Node.js Express: JWT Authentication & Authorization example
Source Code
You can find the complete source code for this tutorial on Github.
Hello, any idea how can i use HttpOnly cookies in angular?
thx
im new to angular and i wanna know somethings, lets say i added a drop list for roles in my front and i couldnt get the value correctly in my back, could you help with it
when i run the application i can’t have anything , i can’t see what is the problem
Hi, did you run any back-end server that I mention in the tutorial?
Hi Bezkoder, first of all, thanks for this awesome tutorial, your tutorials have been helping me a lot!
But i have a question for this one, when I try to create a user with a username that is already registered, the message sended by the server is displayed in the screen (working fine like in the tutorial), but I got a console log in the browser with code 400.
Is this supposed to happen? I know that the api will return this unauthorized code because I can’t create two users with the same username, but how can I handle it in the client?
I want to develop token refresh declaration on Angular, how should I do it instead, can admin help me?
Hi, I will write the tutorial when having time 🙂
Hi Bezkoder,
First of all, thank you for you tutorial !
I only encountered one issue after making some changes.
I solved it but I can’t tell why it didn’t work anymore. Have you got any idea where it might came from ?
This occurred during the login stage, I had to change this line in login.component.ts :
FROM :
this.tokenStorage.saveToken(data.accessToken);
TO :
this.tokenStorage.saveToken(data.token);
Thank you!
Hi, you can check the HTTP response data, you may change the field
accessToken
totoken
. The backend that I used returnsaccessToken
instead oftoken
.I changed the TOKEN_HEADER_KEY from “Authorization” to “x-access-token”.
I also changed this line of code in auth.interceptor.ts:
FROM:
authReq = req.clone({ headers: req.headers.set(TOKEN_HEADER_KEY, ‘Bearer ‘ + token) });
TO:
authReq = req.clone({ headers: req.headers.set(TOKEN_HEADER_KEY, token) });
Hi bezkoder! your tutorial is awesome.
I just want to know what I did wrong in the board component such as (board-admin, board-user, board-moderator). It seems that every time I go to that routes it says “No token provided!”.
By the way I am using nodejs express mongoDB as my backend.
Thank you in advance.
Hi, you need to change some code in interceptor to make this work with x-access-token header instead of Authorization header 🙂
I already resolve my issue.
I moved this line of code “provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true” to app-module.ts and now its work.
Thank you!
hey! First of all thank you very much for your work!
I am currently running the angular 11 frontend on a nodejs express mongoDB api from the backend tutorials as well, and I have two big issues:
First of all i dont seem to be able to alter the styles of the site using any of the .css files, as the changes will simply be ignored when trying to, for example, change the navbar color
Then, after following the integration tutorial to run both projects on the same localhost, i get the error: localhost/:1 Refused to apply style from ‘http://localhost:3000/styles.3ff695c00d717f2d2a11.css’ because its MIME type (‘text/html’) is not a supported stylesheet MIME type, and strict MIME checking is enabled.
I am running the project on port 3000.
Thank you beforehand for your time, it’d be awesome if you could help me!
Hello again. Can you help me with a question?
What happens is that without being logged in and I enter the profile, user, admin, I can enter without problems, how can I do so that it only shows when the admin is logged in, only he can enter the admin route?
OK, Thanks, I already found it
Thank you very much for this great tutorial, I’ve been looking for something like this for a long time.
How are Roles assigned?
I have entered 3 users with the username Admin, Moderator and User and the 3 remain as users
Hi, you can read tutorials for backend that I mention in the tutorial 🙂
Sorry, but I can’t find where the backend tutorials you are talking about are
Hi, it is in the section:
#Run_the_Angular_App
First of all, really great and in detail tutorial, but I have 1 question:
What does ‘f’ mean in the context of ‘f.submitted’, also in ‘f.form’, where does this come from?
Thanks!
It’s a template reference variable, that was declared a couple lines before like this:
Both .submitted and .form are properties of ngForm.
I just realized the codesnipped probably won’t show up properly, it’s (hashtag)f = “ngForm”, it’s line 12 in login component html.
I got an error on auth.interceptors.ts. it was telling me that HttpRequest and the Observable required 1 type argument so I just put any.
there is an error in rendering code at this page. Note the correct return type of intercept method at github
Observable<HttpEvent>
Hi, thank you for your comment. It is code rendering error. I’ve just fixed that. 🙂
Hey, really nice tutorial!
Thank you very much!
plz upload integration of authentication with angular nodejs’
Hi, here you are 🙂
Node.js Express, Angular 10: JWT Authentication & Authorization example