Check Login Using Middleware With NextJS 13
Tags: nextjs, javascript, webdev, react
Published: 2023-09-27 04:33:51

Create a Middleware that checks user login. Here, I have already prepared a BackEnd processing server .
So in this article, we only need to fetch the api and process the returned value. If you have not seen the previous article about Middleware, you can review this link: [Create A Middleware In NextJS 13 - hoanguyenit.com](https://dev.to/skipperhoa/create-a-middleware-in-nextjs-13-17oh)
**CREATE A API FOLDER IN PROJECT **

+ **_app/api/login/route.ts _**
In this **route.ts** file , we will send ( _username_ , _password _) to the backend server to check login. If correct, access_token  will be returned

```javascript
import { NextRequest, NextResponse } from "next/server";
type RequestBody = {
  email: string;
  password: string;
};

export async function POST(request: NextRequest) {
  const body: RequestBody = await request.json();
  const value = {
    email: body.email,
    password: body.password,
  };
  const res = await fetch("https://127.0.0.1:8000/api/auth/login", {
    method: "POST",
    mode: "cors",
    cache: "no-cache",
    credentials: "same-origin",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(value),
  });
  const data = await res.json();
  if (data.success) {
    // Then set a cookie
    const response = NextResponse.json(
      {
        success: data.success,
      },
      { status: 200 }
    );

    response.cookies.set({
      name: "login",
      value: "true",
      httpOnly: true,
    });
    response.cookies.set({
      name: "access_token",
      value: data.access_token, //token value here
      httpOnly: true,
      maxAge: data.expires_in,
    });
    return response;
  }
  return new NextResponse(null, {
    status: 404,
    statusText: "Bad request",
    headers: {
      "Content-Type": "text/plain",
    },
  });
}
```
The backend will return data like ( **access_token , expires_in** ), we can use this data to store it as cookies . 

```javascript
const response = NextResponse.json(
      {
        success: data.success,
      },
      { status: 200 }
    );

    response.cookies.set({
      name: "login",
      value: "true",
      httpOnly: true,
    });
    response.cookies.set({
      name: "access_token",
      value: data.access_token, //token value here
      httpOnly: true,
      maxAge: data.expires_in,
    });
```

![Check Login using Middleware with NextJS 13 - hoanguyenit.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wqwgrim4s5hbd48dh8a4.jpeg)

**CREATE A MIDDLEWARE**
+ **middleware.ts** : used to check access_token , whether it exists or not by using request.cookie.get('_access_token_')

```javascript
import { NextRequest, NextResponse } from "next/server";
const allow_origin_lists :string[]   = process.env.NODE_ENV==='production'?['https://hoanguyenit.com','https://100daysofcode.hoanguyenit.com']:
['https://www.google.com','http://localhost:3000','http://127.0.0.1:3000']
export default function middleware(request: NextRequest){
    const login = request.cookies.get("login");
    const check_login= !login?.value? false: true
    const access_token = request.cookies.get("access_token");
    const check_token = !access_token?.value? false: true
    const origin: string | null  = request.headers.get('origin')
    const res = NextResponse.next()
//    console.log(request.nextUrl.pathname);
    const res_404 = new NextResponse(null,
        {
            status: 404,
            statusText:"Bad request",
            headers:{
                'Content-Type':'text/plain'
            }
        })
    
    if(origin && !allow_origin_lists.includes(origin)){
        return res_404;
    }
    if(!check_login && !check_token){
        return res_404;
    }
    console.log("origin",origin);
    res.headers.append('Access-Control-Allow-Credentials', "true")
    res.headers.append('Access-Control-Allow-Origin', origin) 
    res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT')
    res.headers.append(
        'Access-Control-Allow-Headers',
        'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
    )

    return res;
}
export const config = {
    matcher:[
        '/api/categories:path*',
        '/api/post:path*',
        '/api/user:path*'
    ]
}
```
In the above code, we check the values ​​in the cookie that we saved in the login section above 

```javacript
const login = request.cookies.get("login");
const check_login= !login?.value? false: true
const access_token = request.cookies.get("access_token");
const check_token = !access_token?.value? false: true
//nếu không đúng trả về status 404
if(!check_login && !check_token){
    
    return res_404; 
}
```
Here, we need middleware to request the following api routes:

```javascript
export const config = {
    matcher:[
        '/api/categories:path*',
        '/api/post:path*',
        '/api/user:path*'
    ]
}
```
Okay so we have created Middleware.

Now we need to create a user api folder to get that user's information. If everything in the middleware is correct, it will allow us to call **api/user/**

+ **app/api/user/route.ts**

```javascript
import { NextRequest, NextResponse } from 'next/server'
type ResponseBody = { errors: { message: string }[] } | { username: string };
async function getUserByValidSessionToken(token : string){
  
    const res = await fetch('http://127.0.0.1:8000/api/auth/user-profile',{
         headers: {
           "Content-Type": "application/json",
           "Authorization":"Bearer "+token
         },
    });
   
    const data = await res.json();
    return {
      username: data.name
    }
}

export async function GET(
    request: NextRequest
  ): Promise<NextResponse<ResponseBody>> {
    const token = request.cookies.get("access_token");
    const user = !token?.value
      ? undefined
      : await getUserByValidSessionToken(token.value);
  
    if (!user) {
      return NextResponse.json({
        errors: [{ message: "User not found by session token" }],
      });
    }
  
    return NextResponse.json({
      username: user.username,
    });
```
Get the **access_token** value in the cookie 

```javascript
const token = request.cookies.get("access_token");
    const user = !token?.value
      ? undefined
      : await getUserByValidSessionToken(token.value);
```
Write fucntion fetch **api + token** 

```javascript
const res = await fetch('http://127.0.0.1:8000/api/auth/user-profile',{
         headers: {
           "Content-Type": "application/json",
           "Authorization":"Bearer "+token
         },
});
```

![Create A Middleware In NextJS 13 - hoanguyenit.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8x1jop27bojywg3d9jk7.jpeg)
Okay that's it, you can develop further 
+ Check the token's expiration time, if the Token expires, you can force the user to log in again 
+ If the BackEnd side has a refresh_token
attached , then take the **refresh_token** to see if it's still valid, send it to BackEnd , to get a new  **access_token**
You can see more about [JWT(Json Web Token) In Node.Js](https://hoanguyenit.com/jwt-json-web-token-in-nodejs.html)
The article : [Check Login Using Middleware With NextJS 13](https://hoanguyenit.com/check-login-using-middleware-with-nextjs-13.html)