# JWT authentication with NextJS

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834203142/KFXzvrFP-.png)

### 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)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834204554/w8IMNRqsk.png)

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

### 3\. Client-Side Render (CSR)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834206053/15OY_b5cf.png)

### 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)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834207342/8S8v6hIEk.png)

*   SSG — Static Site Generator

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834208621/85un8DYHa.png)

node --version

npx create-next-app --typescript 

frontend-nextjs-auth

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834210006/OB3UVim9u.png)

npm rum dev

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834211393/j4T0MZ7YJ.png)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834212772/w2wB_-Hxt.png)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834214285/ko05AoAMw.png)

### Node Server

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834215522/YJOL2EyDN.png)

### VSCode Extensions

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834216782/8rM0QXPtb.png)

fsc

*// @flow*

*import* \* *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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834218297/FJxmASzhc.png)

### 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 Pagina1Page

export const  getServerSideProps:*GetServerSideProps* = async(*ctx*:*GetServerSidePropsContext*) => {

return {

props: {

name: 'Pedro Alvares Cabral'

}

}

};

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834219654/jzvOAgRCK.png)

### Static & Dynamic Pages

*   Page 1 = Dynamic Page
*   Page 2 = Static Page

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834221143/bJwRWBw8m.png)

### Static Page = Page2

const Pagina2Page = () => {

return (

<div>

<h1>Pagina 2</h1>

</div>

);

};

export default Pagina2Page

### 5\. AXIOS API Management

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834222767/Ct8JxKofK.png)

Promise based HTTP client for the browser and node.js

### What is Axios?

Axios is a [*promise-based*](https://javascript.info/promise-basics) HTTP Client for `[node.js](https://nodejs.org/)` and the browser. It is [*isomorphic*](https://www.lullabot.com/articles/what-is-an-isomorphic-application) (= 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](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) from the browser
*   Make [http](http://nodejs.org/api/http.html) requests from node.js
*   Supports the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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](http://en.wikipedia.org/wiki/Cross-site_request_forgery)

### Installing

Using npm:

```
$ npm install axios --save
```

### 6\. Login Page

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834224056/pAaujzo7P.png)

Login Page

### Typlical Error between Client Side & Server Side Application Login

*   CORS ERROR

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834225291/yP-bEfgYT.png)

### CORS Communication Error

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834226812/9c38EqmF4.png)

### 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

*   [https://docs.nestjs.com/security/cors](https://docs.nestjs.com/security/cors)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834228204/nKZMgh88h.png)

### JTW Token Successful

{  
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoidXNlcjFAdXNlci5jb20iLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE2NDIyMTczNDcsImV4cCI6MTY0MjIyMzM0N30.t7lvD4Lu5IsWbNg43DySblOEygOY1EV0elF9K0\_BQng"  
}

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834229502/bNK_DARQB.png)

### 7\. Create a Cookie

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834230821/ABd9ZYQ1hS.png)

### Cookie.ts

  
npm install js-cookie --save

npm install @types/js-cookie --save-dev

npm install cookie --save

npm install @types/cookie --save-dev

// -------------------------------------

// Cookie.ts

import 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 Cookie

setCookie('token', data.token);

### Private Page

export const PrivatePage = () => {

return (

<div>

<h1>Pagina Privada</h1>

</div>

);

};

Execution on PORT 3001

PORT=3001 npm run dev

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834232267/FUDehQBJV.png)

### Token JWT

{  
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoidXNlcjFAdXNlci5jb20iLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE2NDIyMjMzOTIsImV4cCI6MTY0MjIyOTM5Mn0.11PtUPUqhjM0JaxNTIP07jjieUDIW79y1\_sITNQZNeI"  
}

### Cookie

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsInVzZXJuYW1lIjoidXNlcjFAdXNlci5jb20iLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE2NDIyMjMzOTIsImV4cCI6MTY0MjIyOTM5Mn0.11PtUPUqhjM0JaxNTIP07jjieUDIW79y1\_sITNQZNeI

### Browser Application

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834233658/jGIHOOSlf.png)

### No Secure Cookie

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834234967/KO9etytmdS.png)

### 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 cooki

const 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 cookie

if (!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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834236299/lUpuAG2lj.png)

withAuth.tsx

### 8\. Authentication Static Page with NextJS

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834237552/vvDOoZDsY.png)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834238806/hL8sz4l2e.jpeg)

*   [https://swr.vercel.app/docs/with-nextjs](https://swr.vercel.app/docs/with-nextjs)
*   Use Hooks

npm install swr --save

*   /src/home/index.tsx
*   /src/hooks/useAuth.ts

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834240107/UZUdnKrwd.png)

*   localhost:3001/

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834241470/JrA4xYnu5.png)

### Dynamic & Static Pages

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1662834242891/iL1Dx1X9Y.png)

### References

*   [https://nextjs.org/](https://nextjs.org/)
*   [https://vercel.com/](https://vercel.com/)
*   [https://jwt.io/](https://jwt.io/)
*   [https://axios-http.com/](https://axios-http.com/)
*   [https://dev.to/chrsgrrtt/easy-user-authentication-with-next-js-18oe](https://dev.to/chrsgrrtt/easy-user-authentication-with-next-js-18oe)
