JWT authentication with NextJS

Andre Vianna
My Dev Zone
Published in
6 min readJan 15, 2022

A Frontend JWT Application

Summary

  1. Introduction
  2. Server Side Render (SSR)
  3. Client Sider Render (CSR)
  4. Static Site Generation (SSG)
  5. AXIOS API Management
  6. Login Page
  7. Create a Cookie
  8. Authentication Static Page with NextJS
  9. References

1. Introduction

NextJS

  • ReactJS Framework
  • Server-Side Rendering (SSR)
  • Running NodeJS Server to rendering WebPages to Client

NextJS Advantages

  • Setup Zero Config
  • Use TypeScript
  • The Best Performance to Rendering WebPages
  • Backend inside NextJS API-Router
  • Access Database inside NextJS
  • Easy Deploy with Vercel
  • Search Engine Optimization (SEO)
  • Compatibility with Olds Browser
  • Zero JavaScript inside Browser
  • Compatible with Internet Explorer
  • API Router

2. Server-Side Render (CSR)

  • Server (NodeJS)
  • API or DataBase
  • Client Browser HTML

3. Client-Side Render (CSR)

ReactJS

  • Client-Side Rendering (CSR)
  • create react app
  • Simple Page Application (SPA)
  • Server
  • Download index.html, app.js ===> Browser
  • ReactDOM
  • All pages inside React App

Problem with CSR

  • Search Engine Optimization (SEO)
  • The Client Browser need extras Resources
  • The difficulty holding data to the navigation
  • Memory Leads
  • Spotify use ReactJS (CSR)
  • Create loadings Indicates

3. Static Site Generation (SSG)

  • SSG — Static Site Generator
node --versionnpx create-next-app --typescript frontend-nextjs-auth
npm rum dev

Node Server

VSCode Extensions

fsc// @flowimport * as React from 'react';type Props = {};export const pagina1 = (props: Props) => {return (<div></div>);};

Static Page

npm run build----------------const Pagina1Page = () => {return (<div><h1>Pagina 1</h1></div>);};export default Pagina1Page

Dynamic Page

import { GetServerSideProps, GetServerSidePropsContext } from "next";import styles from '../styles/Home.module.css'const Pagina1Page = ({name}: {name:any}) => {return (<div><h1>Pagina 1</h1><h2>{name}</h2></div>);};export default Pagina1Pageexport const  getServerSideProps:GetServerSideProps = async(ctx:GetServerSidePropsContext) => {return {props: {name: 'Pedro Alvares Cabral'}}};

Static & Dynamic Pages

  • Page 1 = Dynamic Page
  • Page 2 = Static Page

Static Page = Page2

const Pagina2Page = () => {return (<div><h1>Pagina 2</h1></div>);};export default Pagina2Page

5. AXIOS API Management

Promise based HTTP client for the browser and node.js

What is Axios?

Axios is a promise-based HTTP Client for node.js and the browser. It is isomorphic (= it can run in the browser and nodejs with the same codebase). On the server-side it uses the native node.js http module, while on the client (browser) it uses XMLHttpRequests.

Features

  • Make XMLHttpRequests from the browser
  • Make http requests from node.js
  • Supports the Promise API
  • Intercept request and response
  • Transform request and response data
  • Cancel requests
  • Automatic transforms for JSON data
  • Client side support for protecting against XSRF

Installing

Using npm:

$ npm install axios --save

6. Login Page

Login Page

Typlical Error between Client Side & Server Side Application Login

  • CORS ERROR

CORS Communication Error

  • Server Side
  • Client Side
  • Support Http
  • Setup Backend NestJS
  • Setup Frontend NextJS

Setup CORS Backend NestJS

  • main.ts
{cors:true}import { NestFactory } from '@nestjs/core';import { AppModule } from './app.module';async function bootstrap() {const app = await NestFactory.create(AppModule, {cors:true});await app.listen(3000);}bootstrap();

Setup CORS Frontend NestJS

JTW Token Successful

{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoidXNlcjFAdXNlci5jb20iLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE2NDIyMTczNDcsImV4cCI6MTY0MjIyMzM0N30.t7lvD4Lu5IsWbNg43DySblOEygOY1EV0elF9K0_BQng"
}

7. Create a Cookie

Cookie.ts


npm install js-cookie --save
npm install @types/js-cookie --save-devnpm install cookie --savenpm install @types/cookie --save-dev// -------------------------------------// Cookie.tsimport Cookies from 'js-cookie';export function setCookie(key: string,value: string | object,options?: Cookies.CookieAttributes): void {Cookies.set(key,value, {...options,secure: process.env.NODE_ENV === 'production' ? true: false,})}

login.tsx

import { setCookie } from '../util/cookies';// Set CookiesetCookie('token', data.token);

Private Page

export const PrivatePage = () => {return (<div><h1>Pagina Privada</h1></div>);};

Execution on PORT 3001

PORT=3001 npm run dev

Token JWT

{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoidXNlcjFAdXNlci5jb20iLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE2NDIyMjMzOTIsImV4cCI6MTY0MjIyOTM5Mn0.11PtUPUqhjM0JaxNTIP07jjieUDIW79y1_sITNQZNeI"
}

Cookie

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoidXNlcjFAdXNlci5jb20iLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE2NDIyMjMzOTIsImV4cCI6MTY0MjIyOTM5Mn0.11PtUPUqhjM0JaxNTIP07jjieUDIW79y1_sITNQZNeI

Browser Application

No Secure Cookie

Private Page with Cookie Expiration

import { GetServerSideProps, GetServerSidePropsContext } from "next";import { parseCookies } from "../util/cookies";import { isTokenExpired } from "../util/auth";const PrivatePage = () => {console.log('#########################################################');console.log('Pagina Privada Parte Estática');return (<div><h1>Pagina Privada</h1></div>);};export default PrivatePage;export const  getServerSideProps:GetServerSideProps = async(ctx:GetServerSidePropsContext) => {console.log('#########################################################');console.log('Pagina Privada Parte Dinâmica');console.log('contexto');console.log(ctx.req.headers);// manipulando o cookiconst cookies = parseCookies(ctx.req);console.log('cookies');console.log(cookies);console.log('cookies.token');console.log(cookies.token);console.log('isTokenExpired(cookies.token)');console.log(isTokenExpired(cookies.token));// confirmando cookie// confirmando cookieif (!cookies.token || isTokenExpired(cookies.token)) {return {redirect: {permanent: false,destination: '/login'}}}return {props:{}}}

A Set of Private Page Strategies with NextJS

  • Primary Order Function
  • High Order Function = HOF
  • /src/hof/withAuth.tsx
withAuth.tsx

8. Authentication Static Page with NextJS

npm install swr --save
  • /src/home/index.tsx
  • /src/hooks/useAuth.ts
  • localhost:3001/

Dynamic & Static Pages

--

--

Andre Vianna
My Dev Zone

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