Next.js এর হাতেখড়ি (পর্ব ৯) – Middleware: Auth চেক ও রিডাইরেক্ট

Next.js Middleware Auth চেক ও রিডাইরেক্ট

React এর হাতেখড়ি সিরিজে আমরা ProtectedPage কম্পোনেন্ট বানিয়ে পেজ প্রোটেক্ট করতাম — কিন্তু সমস্যা হলো, পেজ প্রথমে লোড হয়ে যায়, তারপর চেক হয় ইউজার লগইন করা কিনা। Next.js-এর Middleware দিয়ে এই চেক পেজে পৌঁছানোরও আগে করা যায় — এই পর্বে শিখব কীভাবে।

Middleware কী?

Middleware হলো একটা ফাংশন, যা প্রতিটা (বা নির্দিষ্ট) রিকোয়েস্ট Next.js-এর পেজ পর্যন্ত পৌঁছানোর আগেই চলে। এটা রিকোয়েস্ট দেখতে পারে, চাইলে সেটাকে অন্য কোথাও রিডাইরেক্ট করতে পারে, বা আটকে দিতে পারে — Cloudflare এর হাতেখড়ি পর্ব ১২-এর WAF Custom Rule-এর ধারণার মতোই, কিন্তু Next.js-এর নিজস্ব লেয়ারে।

middleware.js — প্রজেক্টের রুটে

এই ফাইলটা app/-এর ভেতরে না, বরং প্রজেক্টের একদম রুটে (app/-এর পাশে) থাকে।

my-first-app/
├── app/
├── middleware.js      ← এখানে, app/-এর বাইরে
└── package.json

সবচেয়ে সহজ Middleware

// middleware.js
import { NextResponse } from "next/server";

export function middleware(request) {
  console.log("রিকোয়েস্ট এলো:", request.nextUrl.pathname);
  return NextResponse.next(); // রিকোয়েস্টকে যেতে দাও
}

NextResponse.next() মানে — "সবকিছু ঠিক আছে, স্বাভাবিকভাবে এগিয়ে যাও"। এটাই ডিফল্ট আচরণ, কিন্তু middleware লেখার সময় সবসময় স্পষ্টভাবে লিখতে হয়।

Auth চেক — Cookie দিয়ে

Firebase এর হাতেখড়ি পর্ব ৩-এর মতোই একটা "কি লগইন করা আছে" চেক, কিন্তু এখানে ব্রাউজারের কুকি পড়ে, ঠিক পর্ব ৫-এর cookies()-এর মতোই একটা ধারণা।

// middleware.js
import { NextResponse } from "next/server";

export function middleware(request) {
  const sessionCookie = request.cookies.get("session");

  // /dashboard-এ যেতে চাইলে, কিন্তু session না থাকলে
  if (request.nextUrl.pathname.startsWith("/dashboard") && !sessionCookie) {
    return NextResponse.redirect(new URL("/login", request.url));
  }

  return NextResponse.next();
}

এখানে ইউজার /dashboard-এ যাওয়ার চেষ্টা করলে, পেজের কোনো কোডই এখনো চলেনি — middleware সবার আগে চেক করে নিয়েছে, আর সেশন না থাকলে সরাসরি /login-এ পাঠিয়ে দিয়েছে।

matcher — কোন রুটে চলবে

ডিফল্টভাবে middleware প্রতিটা রিকোয়েস্টে চলে — এমনকি ছবি, CSS ফাইলেও। এটা অপচয়, তাই config.matcher দিয়ে নির্দিষ্ট করে দেওয়া হয় কোন পাথগুলোতেই শুধু middleware চলবে।

// middleware.js
import { NextResponse } from "next/server";

export function middleware(request) {
  const sessionCookie = request.cookies.get("session");
  if (!sessionCookie) {
    return NextResponse.redirect(new URL("/login", request.url));
  }
  return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard/:path*", "/profile/:path*"], // শুধু এই রুটগুলোতে চলবে
};

:path* মানে — /dashboard, /dashboard/settings, /dashboard/books/1 — সবগুলো ম্যাচ করবে, ঠিক পর্ব ২-এর ডাইনামিক রুটের মতোই একটা প্যাটার্ন।

Firebase Auth-এর সাথে মেলানো — একটা বাস্তব চ্যালেঞ্জ

একটা গুরুত্বপূর্ণ পার্থক্য — Firebase এর হাতেখড়ি পর্ব ৩-এর onAuthStateChanged শুধু ব্রাউজারে কাজ করে, Middleware চলে সার্ভারে। তাই Firebase Auth-এর সাথে Middleware ব্যবহার করতে হলে, লগইনের সময় একটা সেশন কুকি বসাতে হয় (সাধারণত একটা API Route দিয়ে, যা Firebase-এর ID Token যাচাই করে একটা কুকি সেট করে) — সরাসরি Firebase-এর ক্লায়েন্ট state middleware থেকে দেখা যায় না।

// একটা সরলীকৃত ধারণা — লগইন হলে কুকি বসানো (Server Action বা API Route-এ)
"use server";
import { cookies } from "next/headers";

export async function loginAndSetSession(idToken) {
  // এখানে বাস্তবে Firebase Admin SDK দিয়ে idToken যাচাই করা হতো
  cookies().set("session", idToken, { httpOnly: true, secure: true });
}

এই টপিকটা একটা পূর্ণাঙ্গ Auth ইন্টিগ্রেশন প্যাটার্ন, যা পর্ব ১০-এ Firebase-এর সাথে জোড়া লাগানোর সময় আরও বিস্তারিত দেখব — আপাতত মূল ধারণাটা মনে রাখা যথেষ্ট: middleware সার্ভারে চলে, তাই এটাকে সার্ভারে-পড়া-যায় এমন কিছু (কুকি) দিয়েই কাজ করতে হয়

অন্যান্য ব্যবহার — শুধু Auth না

  • A/B টেস্টিং — এলোমেলোভাবে ইউজারদের দুটো ভিন্ন ভার্সনে ভাগ করা
  • Geo-based রিডাইরেক্ট — দেশ অনুযায়ী ভিন্ন ভাষার পেজে পাঠানো (request.geo দিয়ে)
  • Rate Limiting — Cloudflare এর হাতেখড়ি পর্ব ১২-এর ধারণারই একটা Next.js-লেয়ার সংস্করণ, যদিও বড় স্কেলে Cloudflare-এর নিজস্ব সিস্টেমই বেশি কার্যকর

ইন্টারেক্টিভ — Middleware সিদ্ধান্ত সিমুলেশন

নিচে বিভিন্ন পরিস্থিতিতে Middleware কী সিদ্ধান্ত নেবে দেখো।

ভালো অভ্যাস

  • সবসময় matcher নির্দিষ্ট করুন — প্রতিটা রিকোয়েস্টে middleware চালানো অপ্রয়োজনীয় ও ধীর
  • Middleware-এ ভারী কাজ (ডেটাবেজ query) এড়িয়ে চলুন — এটা প্রতিটা রিকোয়েস্টে চলে, তাই দ্রুত হওয়া জরুরি; শুধু কুকি/হেডার চেক করুন
  • Middleware-কে একমাত্র নিরাপত্তা স্তর হিসেবে ধরবেন না — Firebase এর হাতেখড়ি পর্ব ৮-এর Security Rules-এর মতো, ডেটাবেজ পর্যায়েও সবসময় আলাদা সুরক্ষা রাখা উচিত

নিজে চেষ্টা করো

Exercise:

  1. একটা middleware.js বানাও যা প্রতিটা রিকোয়েস্টের path console.log করে।
  2. একটা /dashboard রুট প্রোটেক্ট করো — কুকি না থাকলে /login-এ রিডাইরেক্ট করাও।
  3. config.matcher যোগ করো, দেখো middleware শুধু নির্দিষ্ট রুটেই চলছে কিনা console.log দিয়ে যাচাই করো।
  4. ব্রাউজারের DevTools থেকে ম্যানুয়ালি একটা কুকি সেট করে, তারপর প্রোটেক্টেড রুটে গিয়ে দেখো এখন অ্যাক্সেস মিলছে কিনা।

পরের পর্বে যা থাকছে

পরের পর্বে আমরা শিখব Next.js + Firebase — Firebase Auth ও RTDB এই সিরিজে যা শিখেছি তার সাথে কীভাবে সম্পূর্ণভাবে ইন্টিগ্রেট করতে হয়, সেশন কুকি সেটআপসহ।

একটি মন্তব্য পোস্ট করুন

নবীনতর পূর্বতন

যোগাযোগ ফর্ম