Check Login using Middleware with NextJS 13

Tạo một Middleware kiểm tra sự đăng nhập của user. Ở đây mình đã có chuẩn bị sẵn một server xử lý BackEnd rồi nhé
Nên trong bài này ta chi việc fetch api và xử lý giá trị trả về thôi. Bạn nào chưa xem bài viết trước về Middleware thì có thể vào link này xem lại:Create A Middleware In NextJS 13

# Create a api folder in Project 

+ app/api/login/route.ts 
Trong tệp route.ts này, ta sẽ gửi (username, password) đến server backend để check đăng nhập. Nếu đúng sẽ trả về access_token 

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",
    },
  });
}

Backend sẽ trả về dữ liệu như ( access_token, expires_in) , chúng ta dùng dữ liệu này lưu dưới dạng cookie nhé 

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

# Create a Middleware

+ middleware.ts : dùng để check access_token, có tồn tại hay chưa bằng việt sử dụng request.cookie.get('access_token')

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*'
    ]
}

Trong đoạn code trên ta kiểm tra các giá trị trong cookie mà ta đã lưu ở phần login bên trên 

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; 
}

Còn ở đây, ta cần middleware request các đường route api sau:

export const config = {
    matcher:[
        '/api/categories:path*',
        '/api/post:path*',
        '/api/user:path*'
    ]
}

Okay vậy là ta đã tạo được Middleware xong.

Bây giờ ta cần tạo một folder api user để lấy thông tin của user đó. Nếu mọi thứ ở middleware điều chính xác, nó sẽ cho phép ta gọi tới api/user/

+ app/api/user/route.ts

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,
    });

  }

Lấy giá trị chưa access_token trong cookie 

const token = request.cookies.get("access_token");
    const user = !token?.value
      ? undefined
      : await getUserByValidSessionToken(token.value);

Viết fucntion fetch api + token 

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

Check Login using Middleware with NextJS 13

Okay như vậy là xong rồi đó , bạn có thể phát triển thêm 

+ Check thời gian hết hạn của token , nếu Token hết hạn, bạn có thể bắt người dùng đăng nhập lại

+ Còn nếu bên BackEnd có kèm theo refresh_token , thì lấy refresh_token xem còn hạn không, gửi đến BackEnd, để lấy access_token mới lại 

Bạn có thể xem thêm về JWT(Json Web Token) In Node.Js

Bài Viết Liên Quan

Messsage

Ủng hộ tôi bằng cách click vào quảng cáo. Để tôi có kinh phí tiếp tục phát triển Website!(Support me by clicking on the ad. Let me have the money to continue developing the Website!)