angular-10-jwt-authentication-feature-image

Angular 10 JWT Authentication example with Web Api

In this tutorial, we’re gonna build an Angular 10 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 10 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 10 CRUD Application example with Web API

Fullstack:
Angular 10 + Spring Boot: JWT Authentication & Authorization example
Angular 10 + Node.js Express: JWT Authentication & Authorization example

Overview of Angular 10 JWT Authentication example

We will build an Angular 10 JWT 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:

angular-10-jwt-authentication-signup

– Login Page:

angular-10-jwt-authentication-login

– Profile Page:

angular-10-jwt-authentication-profile

– Navigation Bar for Admin account:

angular-10-jwt-authentication-admin

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 Node.js Express Server:

In the video, we use Node.js Express for back-end REST APIs. You can find explanation and source code at:
Node.js + MySQL: JWT Authentication & Authorization example
Node.js + PostgreSQL: JWT Authentication & Authorization example
Node.js + MongoDB: User Authentication & Authorization with JWT

Logic is the same if you use following Spring Boot back-end:
Secure Spring Boot App with Spring Security & JWT Authentication (MySQL)
– Or MongoDB instead: Spring Boot, MongoDB: JWT Authentication with Spring Security

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 10 Client will make or receive.

angular-10-jwt-authentication-flow

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.

angular-10-jwt-authentication-overview

– 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 10
– RxJS 6

Setup Angular 10 Project

Let’s open cmd and use Angular CLI to create a new Angular Project as following command:

ng new Angular10JwtAuth
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS

We also need to generate some Components and Services:

ng g s _services/auth
ng g s _services/token-storage
ng g s _services/user

ng g c login
ng g c register
ng g c home
ng g c profile
ng g c board-admin
ng g c board-moderator
ng g c board-user

After the previous process is done, under src folder, let’s create _helpers folder and auth.interceptor.ts file inside.

Now you can see that our project directory structure looks like this.

Project Structure

angular-10-jwt-authentication-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 { 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 { 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(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(): void {
    window.sessionStorage.clear();
  }

  public saveToken(token: string): void {
    window.sessionStorage.removeItem(TOKEN_KEY);
    window.sessionStorage.setItem(TOKEN_KEY, token);
  }

  public getToken(): string {
    return sessionStorage.getItem(TOKEN_KEY);
  }

  public saveUser(user): void {
    window.sessionStorage.removeItem(USER_KEY);
    window.sessionStorage.setItem(USER_KEY, JSON.stringify(user));
  }

  public getUser(): any {
    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, 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';

@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 & MongoDB
Spring Boot JWT Authentication with Spring Security & MySQL/PostgreSQL


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 = {};
  isSuccessful = false;
  isSignUpFailed = false;
  errorMessage = '';

  constructor(private authService: AuthService) { }

  ngOnInit(): void {
  }

  onSubmit(): void {
    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=20
  • email: required, email format
  • password: required, minLength=6

register/register.component.html

<div class="col-md-12">
  <div class="card card-container">
    <img
      id="profile-img"
      src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"
      class="profile-img-card"
    />
    <form
      *ngIf="!isSuccessful"
      name="form"
      (ngSubmit)="f.form.valid && onSubmit()"
      #f="ngForm"
      novalidate
    >
      <div class="form-group">
        <label for="username">Username</label>
        <input
          type="text"
          class="form-control"
          name="username"
          [(ngModel)]="form.username"
          required
          minlength="3"
          maxlength="20"
          #username="ngModel"
        />
        <div class="alert-danger" *ngIf="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(): void {
    if (this.tokenStorage.getToken()) {
      this.isLoggedIn = true;
      this.roles = this.tokenStorage.getUser().roles;
    }
  }

  onSubmit(): void {
    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(): 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="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(): 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 & MongoDB
Spring Boot JWT Authentication with Spring Security & MySQL/PostgreSQL

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 10 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 10, HttpInterceptor and Router.

This is tutorial for the older one with Angular version 8:
Angular 8 JWT Authentication with Web Api example

Happy learning, see you again!

Further Reading

Source Code

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

20 thoughts to “Angular 10 JWT Authentication example with Web Api”

    1. Hi, you can write API for updating roles first (with checking Admin role). Then add UI in Admin Board that helps to update users’ role.

  1. Hey there is a one Bug. In backend tutorial we defined a payload JwtResponse withe a field “token” but here we are expecting it as accessToken.

    1. Hi, please notice the getter methods in JwtResponse class. It indicates which fields showing in the HTTP responses 🙂

  2. Dear Bezkoder,

    Thank you very much for your great tutorials!

    I am jsut having one problem, when looking in DevTools in Chrome, -> Application
    I always see Key: auth-user Value: {“token”:”eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbjEiLCJpYXQiOjE1OTgzODUzNzEsImV4cCI6MTU5ODQzMTk1N30.5kN0GlEhzJXqc_3nm-C1OXDHd79jXNl47WxIAo8oUefp4FkoG8Qe9J3gEsbniYQLyn7udfo5u2eoNXB3Ye9r0g”,”type”:”Bearer”,”id”:5,”username”:”admin1″,”email”:”admin1@admin.com”,”roles”:[“USER”]}

    but Key: auth-token Value: undefined

    Do you have an idea how to solve this one?

    Thank you very much in advance
    stay safe and healthy

  3. Hi, thankyou for the tutorial. I want to ask why I cannot navigate to login, signup page and etc? I only get to stay at the home page. Please help.

  4. c.s.demo.security.jwt.AuthEntryPointJwt : Unauthorized error: Full authentication is required to access this resource

    I kept getting this error when I try to access Admin/Mod/User dashboard. Please help.

  5. Thank you very much.
    Maybe you can help with the following error:
    Access to XMLHttpRequest at ‘http://localhost:8080/auth/signin’ 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.
    login.component.ts:64

    error = {“headers”:{“normalizedNames”:{},”lazyUpdate”:null,”headers”:{}},”status”:0,”statusText”:”Unknown Error”,”url”:”http://localhost:8080/auth/signin”,”ok”:false,”name”:”HttpErrorResponse”,”message”:”Http failure response for http://localhost:8080/auth/signin: 0 Unknown Error”,”error”:
    {“isTrusted”:true}}

    I add the configure method as you did and also the “@CrossOrigin(origins = “http://localhost:4200″, maxAge = 3600)” in the controller

  6. hello when I try to register it tells me that the registration has failed. I guess my frontend is not communicating properly with mysql. help please

  7. I Bezccoder. I based on your code and did a similar application. I have created a select which permit the user to choose his role (User or Seller). This don’t work! When i created a new account, the backend set him a user role. how can i do to chane this ( to send differernt role from user to the backend)

  8. first, I would like to thank you for this wonderful work and my question is why you didn’t implement the guard service on it.
    thanks a lot, sir and have a good day.

  9. Thank you for this nice tut !!!
    It work, but i have a Token error …
    I use you NodeJs + Mongo + Express code for the backend, and i don’t find in this front end angular application where put the same «secret» value like in auth.config.js in the server side …

Leave a Reply

Your email address will not be published. Required fields are marked *