In this tutorial, we’re gonna build an Angular 12 Token based Authentication & Authorization (Login and Registration) Application with Web Api and JWT (including HttpInterceptor
, Router & Form Validation). I will show you:
- JWT Authentication Flow for User Registration (Signup) & User Login
- Project Structure for Angular 12 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 CRUD Application example with Web API
– Angular File upload example with Progress bar
Fullstack:
– Angular 12 + Spring Boot: JWT Authentication & Authorization example
– Angular 12 + Node.js Express: JWT Authentication & Authorization example
Newer versions:
– Using Angular 13
– Using Angular 14
Contents
- Overview of Angular 12 JWT Authentication example
- Flow for User Registration and User Login
- Angular App Diagram with Router and HttpInterceptor
- Technology
- Setup Angular 12 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 12 JWT Authentication example
We will build an Angular 12 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 responses
Here are the screenshots of our app:
– Signup/Registration Page:
– Form Validation:
If you want to know more details about Form Validation, please visit:
Angular 12 Form Validation example (Reactive Forms)
– Login Page:
– Profile Page:
– Navigation Bar for Admin account:
For refresh token, please visit:
Angular 12 Refresh Token with Interceptor and JWT example
Demo
This is full Angular 10 (similar to this Angular version 12) 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 12 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.
If you want to store JWT in HttpOnly Cookie, please visit:
Angular 12 JWT Authentication & Authorization with HttpOnly Cookie
Technology
– Angular 12
– RxJS 6
– Angular CLI 12
Setup Angular 12 Project
Let’s open cmd and use Angular CLI to create a new Angular Project as following command:
ng new Angular12JwtAuth
? 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.
If you want to store JWT in HttpOnly Cookie, please visit:
Angular 12 JWT Authentication & Authorization with HttpOnly Cookie
_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 12 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 this Angular 12 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 12 Project to write Login and Registration Services, Components for Token based Authentication and Authorization 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 12, HttpInterceptor and Router.
You will need to implement refresh token:
Angular 12 Refresh Token with Interceptor and JWT example
For other Angular versions, please visit:
– Angular 8
– Angular 10
– Angular 11
– Angular 13
– Angular 14
Happy learning, see you again!
Further Reading
- Angular Form Validation example (Reactive Forms)
- Angular CRUD Application example with Web API
- Angular File upload example with Progress bar
- Angular Pagination example | ngx-pagination
Fullstack:
– Angular 12 + Spring Boot: JWT Authentication & Authorization example
– Angular 12 + Node.js Express: JWT Authentication & Authorization example
Source Code
You can find the complete source code for this tutorial on Github.
If you want to store JWT in HttpOnly Cookie, please visit:
Angular 12 JWT Authentication & Authorization with HttpOnly Cookie
after creating the backend (Spring Boot Login and Registration example with MongoDB) im facing problems to get the jwt tokken and i found out that i have to modify using Local Storage to Cookies … and i have no idea how to apply this modifications can anyone help me
thank you for your effort !!!!!!
Hi , i want to be able to add the role for user when i do signup , because i will have the admin creating accounts so i want him to assign role , when i put an input for role it doesn’t work , can you please provide a solution that works for this ? thanks for the great tutorial by the way !
bookmarked!!, I love your Angular tutorial!
when i run the backend and frontend , the localhost is white and i inspect it i got this:
main.ts:12 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.mjs:391:19)
at Object.provideLocationStrategy [as useFactory] (router.mjs:5899:9)
at Object.factory (core.mjs:11526:1)
at R3Injector.hydrate (core.mjs:11435:1)
at R3Injector.get (core.mjs:11251:1)
at injectInjectorOnly (core.mjs:4741:1)
at Module.ɵɵinject (core.mjs:4745:1)
at Object.Location_Factory [as factory] (common.mjs:770:1)
at R3Injector.hydrate (core.mjs:11435:1)
at R3Injector.get (core.mjs:11251:1)
can someone help me?
Exceptionally well written tutorial!
Hi! Great tutorial, I got to learn very clearly about new concepts
Unfortunately I have an error that i cannot solve, I was hoping you could help me. When compiling and running the “ng serve” I get from login and register pages this error:
“error NG8003: No directive found with exportAs ‘ngModel’. – #username=”ngModel”> ”
I check within app.modules.ts and the import is there. I tried the documentation of Angular but could not fix it either. If you could help it would be amazing.
Thanks
Salamo Alaykom ,
Hope you’re doing well !
I guess this might help you !
https://stackoverflow.com/questions/38648407/angular2-error-there-is-no-directive-with-exportas-set-to-ngform
Nice! Good tutorial, thanks for your work on it.
Had to make a couple changes in login/register.component.html files to resolve syntax errors:
password.errors[‘required’]
I’m using Angular 13 so this is probably what @giraldiego is referring to
Hi, thanks for your comment. There is a tutorial for Angular 13 🙂
Angular 13 Login and Registration example with JWT and Web Api
Great work! Looks very nice.
I have one question. When I start this project locally, I get the response Signup failed after the registration. Do you know this error?
Hi, you can check which backend server you used first.
Then make sure that you have roles table/collection in the database.
Are the roles tables necessary for this to work? I thought it’s just some fruity thing that I can just skip and not do.
in case you are trying this with Angula 13, you need to change the validations from
*ngIf="password.errors?.required"
to
*ngIf="password.errors?.['required']"
Thanks bro , im new to this
Hi, thank you for your tutorial, i want to ask again. Why is it different when i add bootstrapcdn to index.html and when i npm install bootstrap? The differences in the navbar and in the vertical spaces between component (button)
Case closed, it is because of the bootstrap version, i used v. 5.1.3
https://stackoverflow.com/a/67616886/3750918
Thank you
Hi Bezkoder
Thank you for the great tutorials, I have this working perfectly. I have a question, now that I have the three different levels of access (which is exactly what I want) how do I add content to each of their boards.
For example I have the user who can only view the content, the moderator can action the content and the admin can change update and delete the content. I am looking at your CRUD tutorial but I don’t understand how to add that to the existing app
This is all connected to the same tables in the mysql database.
How do I go about that?
Many Thanks
Well-written tutorial! Thanks for your effort!
Failed to load resource: the server responded with a status of 404 (Not Found) – http://localhost:4200/ in angular 12
I have got this error
how to solve this?
Hi, you need to run the backend server first, then run this Angular client with port 8081.
how to run the backend server
You can read the tutorial corresponding to the backend server for instruction.
Hi bezkoder,
I had a small doubt. What if take ‘role’ as an input in Sign Up along with username, email and password? How will the code change? I am working on a project with 3 use cases, user, data provider and admin. I wanted to add role as an input element in Sign up to ask the user to choose between ”ROLE_USER” and “ROLE_DATAPROVIDER”
Hi , did you figure it out ? i’m currently stuck at the same problem and i don’t seem to find an appropriate solution for it ? kindly answer me if u have found a solution for this , thanks !
Hi!:)
I have tried this but if i try to post something to the server from the angular app, it is telling me that there I have no authorization(while logged with admin/user).
On postman, it works with the roles. Thanks!
Hi, kindly make sure that you use the correct Header (Bearer Token for Spring Boot back-end / x-access-token for Node.js back-end).
I have my site already on heroku, and everything is working good, but i need to show or display just some buttons if the user is logged and has ROLE_ADMIN, what can i do?
You can get the user details from LocalStorage or SessionStorage depend on what are you using and there you have also roles (you know the structure of it) – this is made by token-storage service.
Then you can call this service by a method in your component ts file and in html file you can user *ngIf=”isAdminLogged()” and that element will be shown only is this method return true
Hi, these links not work…
Hi, please tell me what your problem is.
hi bezkoder,
i am using your angular 12 nodejs mysql authentication basic code , that is very help full to start application. can you little help me to manage session. Actually when i open application in new tab then user logout. I want to keep login when user open link in new tab. That will help me lot.
Thanks
Hi, you only need to change Session Storage to Local Storage 🙂
Thanks for reply , i tried got success.
Thanks again
Good tutorial! Thanks!
Do you have the source for the Web API piece available anywhere?
Hi, you can find the Github source code in back-end server tutorials that I mentioned in Run Angular App section.
Hello Bezcoder,
I have tried your tutorial on my application for my schoolproject I thank you for that, it’s work but now I can’t get my API Rest it’s answer :
Access to XMLHttpRequest at ‘http://localhost:8080/tournaments/1’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
I would like to know how can I resolve it please.
it’ s the same for method post and put.
but I just can get a list of tournaments at ‘http://localhost:8080/tournaments’
Thank’s for all,
Ludovic, a french student.
Hi, you need to run your Angular client at port 8081 for passing CORS policy.
The command is:
ng serve --port 8081
.Enabled CURD from Back-end
Thank you for your tutorials
I have a little bit of a different setup
I am displaying the application based on someone already authenticated (from a different app, then routed to my application). I am consuming a token and displaying an appropriate page based on their credentials
If possible could you show how to consume this token and display a admin page or user type page?
Thank you in advance
Rob
in addition the backend is SpringBoot
can know the backend example with .net