JWT authentication with NestJS

Andre Vianna
My Dev Zone
Published in
7 min readJan 8, 2022

A Backend JWT Application

Summary

  1. What is NestJS?
  2. What is JWT?
  3. Starting the NestJS Backend
  4. NestJS Modules & Components
  5. Bcrypt Password
  6. REST Client for VSCode
  7. JWT Token
  8. Passport NodeJS Authentication
  9. References

1. What is NestJS?

  • NestJS is a Node Framework 🆓
  • Since 2017 🆕
  • CoC — Convention Over Configuration 🧾
  • TypeScript´👨‍💻
  • Scalable Architecture 🧗‍♀️
  • Integration with multiple databases 💿
  • MicroService Support 🚀
  • API REST 📲

Value offer

The NestJS Value Proposition is to use an MVC architecture in an agile way

NestJS Language

Uses TypeScript as a development language, Jest with Test Tools, and AngularJS concepts

NestJS with Postgres Database

The NestJS Value Proposition is to use an MVC architecture in an agile way

TypeORM with Nest JS Application API development – @tkssharma | Tarun  Sharma | My Profile

2. What is JWT?

  • JSON Web Token
  • API REST-based on HTTP Stateless requisition
  • Uses a Token and not a Cookie

Use Cases with Cookie Auth

  • Only Web Browser Application

Use Cases with Token Auth

  • Mobile
  • Desktop
  • CLI
  • IoT
Cookie Auth vs Token Auth

3. Starting the NestJS Backend

node --versionnpm install -g @nestjs/clinest new authentication-with-NestJS
¨npm run start:dev

4. Concepts of NestJS?

a) NestJS Modules & Components

  • Module A to Feature 1
  • Module B to Feature 2
Clean Architecture

b) Clean Architecture

  • Use Case ===> Feature
  • Repository Interfaces
  • Domain Services
  • Domain Model

c) Generate an NestJS Module

nest g module auth// Output/src/auth/auth.module.ts
after auth module
after auth module

c) Generate an NestJS Controller

/                   // root
/auth // auth module
/auth/login // controler login
nest g controller auth/login
login controller
  • login.controller.spec.ts
import { Test, TestingModule } from '@nestjs/testing';import { LoginController } from './login.controller';describe('LoginController', () => {let controller: LoginController;beforeEach(async () => {const module: TestingModule = await Test.createTestingModule({controllers: [LoginController],}).compile();controller = module.get<LoginController>(LoginController);});it('should be defined', () => {expect(controller).toBeDefined();});});
  • login.controller.ts
import { Controller } from '@nestjs/common';@Controller('login')export class LoginController {}/                   // root
/auth // auth module
/auth/login // controler login
/auth/auth // controler auth
// Generate Auth Controller
nest g controller auth/auth

// Generate Auth Service to Access Database
nest g service auth/auth

5. BCrypt Password

bcrypt is a password-hashing function designed by Niels Provos and David Mazières, based on the Blowfish cipher and presented at USENIX in 1999.[1] Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

The bcrypt function is the default password hash algorithm for OpenBSD[2] and was the default for some Linux distributions such as SUSE Linux.[3]

npm install bcrypt --save

generate-pass.js

const bcrypt = require('bcrypt');const saltRounds = 10;const password = process.argv.slice(2)[0];bcrypt.genSalt( saltRounds,function(err, salt){bcrypt.hash(password, salt, function(err,hash){console.log(hash)})});

Password Generate

node generate-pass.js 12345678910
❯ node generate-pass.js 12345678910
$2b$10$OLBu.sG9stD6j3PpeO6sw.QuZmxk4RUnfMVTJ.8afMLdj/9HwsRGC

6. REST Client for VS CODE

REST ClientGET https://example.com/comments/1 HTTP/1.1

###

GET https://example.com/topics/1 HTTP/1.1

###

POST https://example.com/comments HTTP/1.1
content-type: application/json

{
"name": "sample",
"time": "Wed, 21 Oct 2015 18:27:50 GMT"
}

POST Method

GET Method

7. JWT Token

  • JWT — JSON Web Token
  • Header
  • Payload
  • Signature
  • AutoContent

JWT = (1) Header + (2) Payload + (3) Signature

1) Header

2) Payload

  • jwt.ts
const header: {alg: string, typ: string; } = {alg: 'HS256',typ: 'JWT',};const payload: {username: string; name:string; exp:number;} = {username: 'user1@user.com',name: 'Luiz Carlos',exp: new Date().getTime(), //timestamp};const key: "abcd123456" = 'abcd123456';// header + payload + key// base64const headerEncoded = Buffer.from( JSON.stringify(header)).toString("base64");const payloadEncoded = Buffer.from( JSON.stringify(payload)).toString("base64");console.log("1.0) Header -----------------------------------");console.log("1.1) header         > ", header);console.log("1.2) headerEncoded  > ", headerEncoded);console.log("2.0) Payload -----------------------------------");console.log("2.1) payload        > ", payload);console.log("2.2) payloadEncoded > ", payloadEncoded);node_modules/.bin/ts-node jwt.ts

3) Signature

const key: "abcd123456" = 'abcd123456';const crypt = require('crypto');const signature = crypt.createHmac('sha256',key).update(`${headerEncoded}.${payloadEncoded}`).digest("bin");console.log("3.0) Signature  -----------------------------------");console.log("3.1) signature         > ", signature);
Header + Payload + Signature = JWT

Install Library base64-URL

npm install base64-url  --save

Implementation base64Url(signature)

const base64Url = require('base64url');console.log("Token JWT - JSON Web Token Created");console.log("JWT = [Header] + [Payload] + [Signature]");console.log("JWT [Token]             >",`${headerEncoded}.${payloadEncoded}.${base64Url(signature)}`);

Token JWT = [header] + [Payload] + [Signature]

Token JWT

JWT [Token]             > eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxQHVzZXIuY29tIiwibmFtZSI6Ikx1aXogQ2FybG9zIiwiZXhwIjoxNjQxNzk4ODA5MjM2fQ==.WS6MhFktJki4cZSZu56mu1rFVUG7ANJfZfJhTfXpWwo

Validation Token JWT

JWT with Bug 🏸

https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxQHVzZXIuY29tIiwibmFtZSI6Ikx1aXogQ2FybG9zIiwiZXhwIjoxNjQxNzk4ODA5MjM2fQ%3D%3D.WS6MhFktJki4cZSZu56mu1rFVUG7ANJfZfJhTfXpWwo

Validation JWT Token

JWT Correct !!!🚀

  • Token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxQHVzZXIuY29tIiwibmFtZSI6Ikx1aXogQ2FybG9zIiwiZXhwIjoxNjQxNzk5NTkzMDc4fQ==.m9DFawDnG07PErE1PN8v0YMDN2xBFX2b6Xv8qOf_7mw
  • Secret
const key: "abcd123456" = 'abcd123456';
Validation JWT Ok

Othe Example

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxQHVzZXIuY29tIiwibmFtZSI6Ikx1aXogQ2FybG9zIiwiZXhwIjoxNjQxODAxMDg3NTkxfQ.wF9iAYt9vqhHHgutq8bEWPO7HPDwAAP5Np3gj_VfjG8

8. Passport NodeJS Authentication

Simple, unobtrusive authentication for Node.js

app.js — vim

passport.authenticate(‘facebook’);(‘google’);(‘apple’);(‘microsoft’);(‘twitter’);(‘linkedin’);(‘github’);(‘openid’);

Passport is authentication middleware for Node.js. Extremely flexible and modular, Passport can be unobtrusively dropped in to any Express-based web application. A comprehensive set of strategies support authentication using a username and password, Facebook, Twitter, and more.

npm install passport --savenpm install passport-jwt --savenpm install @types/passport --save-devnpm install @types/passport-jwt --save-devnpm install @nestjs/jwt

NestJS Generate Auth Strategy

nest g service auth/jwt-strategynpm install @nestjs/passport --save

Test Application

npm run start:dev

Test API

/api/post.api.htpp
Running API Test

Our JWT Token

"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoidXNlcjFAdXNlci5jb20iLCJpYXQiOjE2NDE4NDQyNDUsImV4cCI6MTY0MTg0NDMwNX0.1mH-PD-s8712sILMCMBQX0_KlDX0df3jNneo_bIhb00"

Access control with Token Authenticated

  • Guardian Tokens Access Authenticated
@UseGuards(JwtGuard)
  • authController.ts
import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common';import { AuthService } from './auth.service';import { JwtGuard } from './jwt.guard';@Controller()export class AuthController {constructor(private authService: AuthService){}@Post('login')login(@Body() body ): {token:string} {return { token: this.authService.login(body.username, body.password)}}// Criação Guardiao@UseGuards(JwtGuard) // <<<<< Guardian Token@Get('autenticado')test(){return {name: "Pedro Alvares Cabral"}}}

No Authorization Token

Authorization Token

--

--

Andre Vianna
My Dev Zone

Software Engineer & Data Scientist #ESG #Vision2030 #Blockchain #DataScience #iot #bigdata #analytics #machinelearning #deeplearning #dataviz