مبانی و مفاهیم برنامه‌نویسی

راهنمای جامع احراز هویت در Next.js

راهنمای جامع احراز هویت در Next.js

موضوع احراز هویت (Authentication) در Next.js یکی از کلیدی‌ترین و پراهمیت‌ترین مباحث در توسعه وب مدرن است. با تکامل فریم‌ورک Next.js و استقرار کامل معماری App Router، نحوه هندل کردن امنیت، مدیریت نشست‌ها (Session Management) و کنترل سطوح دسترسی (Authorization) دستخوش تغییرات مهمی شده است. در این مقاله جامع، ابتدا معماری احراز هویت را طبق سند رسمی Next.js بررسی می‌کنیم، سپس سناریوی پیاده‌سازی اختصاصی با **Prisma** و **Credentials** را همراه با نمونه‌کدهای واقعی تحلیل کرده و در نهایت به مقایسه ۱۲ کتابخانه و سرویس برتر Auth در بازار کار می‌پردازیم.

۱. سند رسمی Next.js درباره احراز هویت چه می‌گوید؟

بر اساس راهنمای رسمی Next.js، خود فریم‌ورک یک سیستم اختصاصی و داخلی برای مدیریت کاربر ارائه نمی‌دهد، بلکه ابزارهایی مانند Server Actions، Middleware و Server Components را در اختیار شما می‌گذارد تا لایه امنیت را پیاده‌سازی کنید. سند رسمی Next.js سیستم Auth را به سه مفهوم پایه تقسیم می‌کند:

  • Authentication (احراز هویت): تایید هویت کاربر با استفاده از اعتبارنامه‌ها (ورودی نام کاربری/رمز عبور، کد یک‌بارمصرف یا سرویس‌های OAuth).
  • Session Management (مدیریت نشست): حفظ وضعیت ورود کاربر بین درخواست‌های مختلف به دو روش:
    • Stateless (بدون حالت): استفاده از کوکی‌های رمزشده یا JWT که داده روی مرورگر ذخیره می‌شود.
    • Stateful (با حالت): ذخیره Session ID در دیتابیس و نگهداری شناسه جلسه در کوکی.
  • Authorization (سطوح دسترسی): تعیین این‌که کاربر به کدام صفحات، APIها یا داده‌ها دسترسی دارد که معمولاً از طریق لایه DAL (Data Access Layer) و Server Components مدیریت می‌شود.
How to implement authentication

How to implement authentication

۲. پیاده‌سازی اختصاصی احراز هویت (Credentials + Prisma)

در بسیار از دوره‌های آموزشی و پروژه‌های واقعی، توسعه‌دهندگان ترجیح می‌دهند کنترل کاملی روی داده‌های کاربر داشته باشند. یک الگوی رایج، کاربردی و استاندارد در Next.js، پیاده‌سازی سیستم ورود اختصاصی با Credentials Provider و اتصال به دیتابیس با Prisma ORM است.

برای درک بهتر نحوه ساخت این لایه، ساختار کدهای اصلی و کلیدی این روش به شرح زیر است:

۱. پیکربندی پرووایدر Credentials و اتصال به دیتابیس (`lib/auth.js`)

در این فایل، منطق استعلام کاربر از دیتابیس، اعتبارسنجی کلمه‌عبور هش‌شده و بازگرداندن اطلاعات کاربر تنظیم می‌شود:

import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcryptjs";
import prisma from "@/lib/prisma";

export const authOptions = {
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" }
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) {
          return null;
        }

        // استعلام کاربر از دیتابیس با Prisma
        const user = await prisma.user.findUnique({
          where: { email: credentials.email }
        });

        if (!user || !user.password) {
          return null;
        }

        // بررسی صحت کلمه‌عبور هش‌شده
        const isValid = await bcrypt.compare(credentials.password, user.password);

        if (!isValid) {
          return null;
        }

        return {
          id: user.id,
          email: user.email,
          name: user.name,
        };
      }
    })
  ],
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
};

۲. ایجاد Route Handler برای درخواست‌های NextAuth (`app/api/auth/[…nextauth]/route.js`)

در App Router، نقطه ورود درخواست‌های مربوط به ورود، خروج و مدیریت Session از طریق فایل Route مدیریت می‌شود:

import NextAuth from "next-auth";
import { authOptions } from "@/lib/auth";

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

۳. ساخت API ثبت‌نام کاربر جدید با اعتبارسنجی سمت سرور (`app/api/register/route.js`)

قبل از اینکه کاربر بتواند وارد شود، ابتدا باید اکانت خود را ایجاد کند. کدهای سمت سرور برای هش کردن پسورد و ایجاد رکورد جدید در دیتابیس به این صورت است:

import { NextResponse } from "next-auth";
import bcrypt from "bcryptjs";
import prisma from "@/lib/prisma";

export async function POST(req) {
  try {
    const { name, email, password } = await req.json();

    if (!email || !password) {
      return NextResponse.json({ message: "اطلاعات ورودی ناقص است" }, { status: 400 });
    }

    // بررسی عدم وجود ایمیل تکراری
    const existingUser = await prisma.user.findUnique({
      where: { email }
    });

    if (existingUser) {
      return NextResponse.json({ message: "این ایمیل قبلاً ثبت شده است" }, { status: 400 });
    }

    // هش کردن پسورد و ذخیره کاربر در دیتابیس
    const hashedPassword = await bcrypt.hash(password, 10);
    const user = await prisma.user.create({
      data: {
        name,
        email,
        password: hashedPassword,
      }
    });

    return NextResponse.json({ message: "کاربر با موفقیت ایجاد شد", userId: user.id }, { status: 201 });
  } catch (error) {
    return NextResponse.json({ message: "خطای سرور" }, { status: 500 });
  }
}

۴. محافظت از صفحات و چک کردن Session

پس از پیاده‌سازی لایه بک‌اند، برای چک کردن دسترسی کاربر در صفحات محافظت‌شده (مثل `/dashboard`) از منطق ساده زیر در Server Components استفاده می‌شود:

import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { redirect } from "next/navigation";

export default async function DashboardPage() {
  const session = await getServerSession(authOptions);

  if (!session) {
    redirect("/login");
  }

  return (
    <div>
      <h1>خوش آمدید، {session.user.name}</h1>
      <p>این صفحه فقط برای کاربران واردشده قابل مشاهده است.</p>
    </div>
  );
}

۳. لایبرری‌ها و کتابخانه‌ها دقیقاً چه کاری انجام می‌دهند؟

اگرچه پیاده‌سازی صفر تا صد احراز هویت باعث درک عمیق مفاهیم می‌شود، اما نوشتن تمامی موارد (از رمزشادن کوکی‌ها تا چرخش توکن و جلوگیری از حملات CSRF و XSS) پیچیده و زمان‌بر است. کتابخانه‌های Auth این مسئولیت‌ها را بر عهده می‌گیرند:

  • حذف کدهای تکراری (Boilerplate): عدم نیاز به نوشتن دستی منطق هش پسورد، ساخت کوکی Secure/HttpOnly و الگوریتم‌های رمزنگاری.
  • اتصال آسان به شبکه‌های اجتماعی (OAuth): پیاده‌سازی ورود با اکانت گوگل، گیت‌هاب و اپل تنها با چند خط کانفیگ.
  • ارتقای امنیت استاندارد: رعایت آخرین استانداردهای امنیتی، انقضای خودکار توکن‌ها و جلوگیری از حملات رایج وب.
  • امکانات مدرن آماده: قابلیت‌هایی نظیر ورود بدون پسورد (Passkeys)، احراز هویت دو عاملی (2FA) و مدیریت نقش‌ها.

۴. بررسی و مقایسه ۱۲ ابزار برتر احراز هویت در Next.js

ابزارهای موجود در بازار را می‌توان به دو دسته کلی تقسیم کرد: کتابخانه‌های Open-Source / Self-Hosted (ارائه کنترل کامل روی دیتابیس شخصی) و سرویس‌های ابری Managed Auth (ارائه سرعت توسعه بالا و UI آماده).

کتابخانه‌های اپن‌سورس و Self-Hosted

  • Better Auth: مدرن‌ترین و پرطرفدارترین کتابخانه اخیر در اکوسیستم TypeScript. دارای آداپتورهای قدرتمند برای Prisma و Drizzle، و پشتیبانی نیتیو از Passkey، OTP و نقش‌ها (RBAC).
  • NextAuth.js / Auth.js: شناخته‌شده‌ترین راهکار اکوسیستم Next.js. نسخه ۵ (v5) آن اختصاصاً برای App Router و Server Actions از نو بازنویسی شده است.
  • Ory (Kratos / Hydra): راهکار اپن‌سورس و بسیار قدرتمند مبتنی بر زبان Go، مناسب برای معماری‌های پیچیده Enterprise و میکروسرویس‌ها.

سرویس‌های ابری و Managed Auth

  • Clerk: محبوب‌ترین سرویس ابری در پروژه React/Next.js. ارائه کامپوننت‌های آماده و بسیار زیبای UI و پشتیبانی عالی از ساختارهای چندمستاجری (Multi-tenancy / SaaS).
  • Kinde: رقیب مستقیم Clerk با سرعت راه‌اندازی بالا و امکانات ویژه برای استارتاپ‌ها مانند مدیریت Feature Flagها.
  • Logto: جایگزین اپن‌سورس Clerk که هم نسخه ابری دارد و هم امکان نصب روی سرور شخصی (Self-host) را فراهم می‌کند.
  • Stack Auth: ابزاری جدید و اپن‌سورس با یکپارچگی عمیق در App Router برای ارائه کامپوننت‌های آماده در کنار قابلیت Self-host.
  • WorkOS: استاندارد طلایی پروژه‌های B2B Enterprise برای اتصال به SSO سازمان‌ها (SAML/Okta) و همگام‌سازی کاربران (SCIM).
  • Stytch: تمرکز ویژه روی راهکارهای Passwordless (Magic Link، بیومتریک، SMS OTP) و ابزارهای پیشرفته ضد تقلب.
  • Descope: پلتفرم Visual / Low-Code که اجازه می‌دهد فرآیند ورود و ثبت‌نام را به‌صورت دیداری طراحی کنید.
  • Auth0 (توسط Okta): قدیمی‌ترین و جامع‌ترین سرویس ابری Auth با امکانات فراوان اما کانفیگ نسبتاً پیچیده‌تر.
  • Supabase Auth: سیستم Auth نیتیو Supabase که مستقیماً با Row Level Security (RLS) دیتابیس PostgreSQL یکپارچه می‌شود.

۵. جدول مقایسه سریع ابزارهای احراز هویت

جدول زیر خلاصه عملکرد مطرح‌ترین گزینه‌ها را نشان می‌دهد:

نام ابزار نوع ساختار کنترل دیتابیس UI آماده؟ سناریوی پیشنهادی
Better Auth Open-Source / Lib کامل (دیتابیس شخصی) خیر پروژه‌های جدید Next.js با کنترل کامل داده‌ها
NextAuth.js (v5) Open-Source / Lib کامل (دیتابیس شخصی) خیر پروژه‌های استاندارد و برنامه‌نویسی مستقل
Clerk Managed Cloud میزبانی ابری بله (کامل) توسعه سریع پروژه‌های تجاری و SaaS
Supabase Auth BaaS / Postgres دیتابیس Supabase محدود پروژه‌های مبتنی بر پلتفرم Supabase
WorkOS Managed Cloud میزبانی ابری بله سامانه‌های B2B و فروش به سازمان‌های بزرگ
Logto Open-Source / Cloud هر دو حالت بله تجربه مشابه Clerk همراه با قابلیت Self-host

۶. نتیجه‌گیری و جمع‌بندی

انتخاب بهترین روش احراز هویت در Next.js مستقیماً به اهداف پروژه بستگی دارد. اگر قصد دارید سیستم کاملاً مستقلی داشته باشید که داده‌ها در دیتابیس خودتان (با Prisma یا Drizzle) مدیریت شوند، ابزارهایی مانند Better Auth یا Auth.js v5 بهترین گزینه‌ها هستند. اما اگر سرعت توسعه، تجربه کاربری مدرن و عدم درگیری با پیچیدگی‌های امنیتی در اولویت است، سرویس‌هایی مانند Clerk انتخاب اول بازار کار خواهند بود.

در دوره آموزش Next js سماتک، تمام این مفاهیم به‌صورت سناریومحور و کاملاً پروژه‌ای آموزش داده می‌شوند تا دانشجویان پس از پایان دوره توانایی پیاده‌سازی انواع سیستم‌های احراز هویت را در پروژه‌های واقعی داشته باشند.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *