JWT authentication with NextJS
Published in
6 min readJan 15, 2022
A Frontend JWT Application
Summary
- Introduction
- Server Side Render (SSR)
- Client Sider Render (CSR)
- Static Site Generation (SSG)
- AXIOS API Management
- Login Page
- Create a Cookie
- Authentication Static Page with NextJS
- 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
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 --savenpm 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
8. Authentication Static Page with NextJS
npm install swr --save
- /src/home/index.tsx
- /src/hooks/useAuth.ts
- localhost:3001/