پیاده‌سازی سیستم احراز هویت در Next.js بوسیله Clerk
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 8 دقیقه

پیاده‌سازی سیستم احراز هویت در Next.js بوسیله Clerk

مدیریت کاربران و راه‌اندازی یک سیستم احراز هویت قدرتمند یکی از اصلی‌ترین نیازمندی‌های هر وبسایت و اپلیکیشن امروزی است. شما از طریق پیاده‌سازی چنین سیستمی به خوبی می‌توانید از داده‌های‌تان حفاظت کنید و نگذارید هر کسی به راحتی به پنل ادمین شما دسترسی پیدا بکند. توسعه دهندگان نیز معمولا در پیاده‌سازی چنین سیستمی با چالش و مشکل روبرو می‌شوند، دلیل آن نیز پیچیدگی نسبی چنین سیستم‌هایی‌ست.

Next.js یک فریمورک محبوب مبتنی بر React.js است و اکو سیستم فوق‌العاده‌ای را برای توسعه اپلیکیشن‌ها ایجاد کرده، اما مشکلاتی مانند پیاده‌سازی سیستم احراز هویت به خوبی در این چهارچوب در نظر گرفته نشده و به همین دلیل اگر اپلیکیشنی مبتنی بر این فریمورک ایجاد کنید در پیاده‌سازی یک سیستم احراز هویت ممکن است با چالش‌ها و مشکلات مختلفی روبرو شوید.

در این مطلب از وبسایت راکت قصد داریم با کمک سرویس احراز هویت Clerk برای اپلیکیشن‌های مبتنی بر Next.js یک سیستم احراز هویت ایجاد کنیم. در این مسیر شما را نیز با این ابزار آشنا کرده و یک مثال عملی را با همدیگر پیش می‌بریم.

Clerk چیست؟

Clerk یک سرویس احراز هویت مبتنی بر کلود است که فرایند ادغام یک سیستم احراز هویت با وب اپلیکیشن شما را ساده می‌کند. با استفاده از این سرویس شما می‌توانید روی جنبه‌های دیگر وب اپلیکیشن‌تان کار بکنید و در ارتباط با پیاده‌سازی سیستم مذکور نگرانی نداشته باشید. پس در واقع شما برای پیاده‌سازی سیستم احراز هویت، سرویس Clerk را استخدام می‌کنید. با استفاده از Clerk شما می‌توانید کارهای مختلفی را انجام دهید که چند مورد آن را در زیر مشاهده می‌کنید:

  • پیاده‌سازی قابلیت ورود سریع با استفاده از اکانت‌های گوگل، گیت‌هاب، توییتر و... .
  • پیاده‌سازی قابلیت ورود یک بار مصرف با استفاده از پیامک یا ایمیل.
  • اضافه کردن قابلیت‌هایی مانند Session Management و Password Protection به فرایند احراز هویت.
  • در اختیار گرفتن یک داشبورد مستقل و کامل برای مدیریت کاربران، نقش‌های مختلف و مجوز‌های دسترسی.

حال که به صورت کلی با Clerk آشنا شدیم بیایید تا مثال عملی که قول‌ش را دادیم پیاده‌سازی کنیم.

پیاده‌سازی پروژه مبتنی بر Next.js

ابتدا کار برای اینکه طول این مقاله زیاد نباشد به جای پیاده‌سازی پروژه Next.js از ابتدا، از یک اپلیکیشن یادداشت برداری آماده استفاده می‌کنیم که با استفاده از Next.js، Typescript و TailwindCSS نوشته شده است استفاده می‌کنیم. برای اینکار ابتدا از مخزن زیر گیت‌هاب را دریافت کرده و سپس پکیج‌های مورد نیاز را با استفاده از npm install نصب کنید:

git clone -b starter git@github.com:am-miracle/secured-note-manager.git
cd secured-note-manager
npm install

حال برای اجرا اپلیکیشن در محیط dev از دستور npm run dev استفاده می‌کنیم و در مرورگر به آدرس localhost:3000 مراجعه می‌کنیم. با انجام تمام این موارد باید خروجی شبیه به تصویر زیر را در اختیار داشته باشید:

خروجی اپلیکیشن next.js-

از آنجایی که اپلیکیشن را از ابتدا ایجاد نکرده‌ایم، می‌توانید با کمی کار کردن با آن منطق کلی آن را درک کنید.

ادغام پروژه با سرویس Clerk

اولین قدم برای در اختیار گرفتن Clerk نصب کردن آن با استفاده از npm است. برای اینکار دستور زیر را در ترمینال وارد کنید:

npm install @clerk/nextjs

بعد از اینکار نیاز است که API Key مربوط به سرویس Clerk را به پروژه معرفی کنیم. برای اینکار ابتدا یک فایل با نام .env.local را ایجاد کنید و سپس محتویات زیر را در آن قرار دهید:

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=<your clerk public key>
CLERK_SECRET_KEY=<your clerk secret key>

برای دریافت Public Key و Secret Key نیاز است که وارد وبسایت Clerk شده و یک اکانت جدید را ایجاد کنید. بعد از این کار وارد قسمت داشبورد شده و یک اپلیکیشن جدید را مانند تصویر زیر ایجاد کرده و به آن یک اسم جدید بدهید:

محیط سرویس Clerk

زمانی که اپلیکیشن جدید را ایجاد کردید، داشبورد اپلیکیشن شما به صورت زیر خواهد بود. همانطور که در تصویر مشاهده می‌کنید Public و Secret Key شما تولید شده و حال باید آن را در فایل .env.local قرار دهید:

محیط Clerk و اپلیکیشن جدید-

همچنین با مطالعه Clerk Docs می‌توانید با گزینه‌ها و ويژگی‌های دیگر این سرویس احراز هویت آشنا شوید.

استفاده از ویژگی‌های سرویس Clerk

بعد از نصب کردن Clerk نیاز است که ClerkProvider را به تمام برگه‌های اپلیکیشن Next.js اضافه کنیم. برای اینکار وارد فایل layout.tsx شده و از دستور import استفاده کنید. به قطعه کد زیر توجه کنید:

// layout.tsx
/** other imports **/
import { ClerkProvider } from "@clerk/nextjs";
export default function RootLayout({
 children,
}: {
 children: React.ReactNode
}) {
 const year = new Date().getFullYear();
 return (
  <ClerkProvider>
   <html lang="en" className="m-0 p-0 box-border">
    <body className={`${inter.className} w-full h-screen px-4`}>
     <Header />
     {children}
     <footer className="text-xl text-gray-400 text-center">
      Note-Keeper {year}
     </footer>
    </body>
   </html>
  </ClerkProvider>
 );
}

با انجام این کار می‌توانید به ویژگی‌های سرویس احراز هویت Clerk دسترسی پیدا کنید.

پیاده‌سازی عملیات‌های ثبت نام، ورود و خروج

مطمئنا ما نمی‌خواهیم که هر کاربری که وارد وبسایت می‌شود بتواند یک یادداشت جدید را اضافه یا حذف بکند. برای اینکه این کاربران بتوانند چنین کارهایی را انجام دهند ابتدا باید وارد اپلیکیشن شوند. برای اینکه این قسمت‌ها را به سرعت ایجاد کنید، Clerk یکسری کامپوننت از پیش تعریف شده را برای ورود و ثبت نام و... ایجاد کرده که می‌توانید از آن‌ها استفاده بکنید. قبل از هر چیزی وارد فایل app/header.tsx شوید و براساس کدهای زیر آن را آپدیت کنید:

"use client";
import {
 SignInButton,
 SignOutButton,
 SignUpButton,
 useClerk,
} from "@clerk/nextjs";
import Image from "next/image";
import Link from "next/link";
import React from "react";
const Header = () => {
 const { user } = useClerk();
 return (
  <nav className="relative flex w-full items-center justify-between bg-inherit py-4 shadow-sm shadow-neutral-700/10">
   <div className="container mx-auto">
    <div className="flex w-full flex-wrap items-center justify-between">
     <div className="flex items-center">
      <Link className="text-white text-xl" href="/">
       Note-Keeper
      </Link>
     </div>
     {user ? (
      <div className="my-1 flex items-center gap-2">
       <div className="h-10 w-10 rounded-full flex items-center justify-center border-blue-800 border">
        <span>
         {`${
          user.firstName && user.lastName
           ? `${user.firstName
             .slice(0, 1)
             .toUpperCase()}${user.lastName
             .slice(0, 1)
             .toUpperCase()}`
           : user.username || ""
         }`}
        </span>
       </div>
       <SignOutButton />
      </div>
     ) : (
      <div className="my-1 flex items-center gap-2">
       <SignInButton />
       <SignUpButton />
      </div>
     )}
    </div>
   </div>
  </nav>
 );
};
export default Header;

همانطور که مشاهده می‌کنید ما کامپوننت‌های SignInButton، SignOutButton، SignUpButton و useClerk را از طریق @clerk/nextjs به کد اضافه کرده‌ایم. useClerk در واقع یک هوک است که به آبجکت یا شئ Clerk دسترسی پیدا می‌کند و آبجکت‌های ClerkJS SDK و متدهای مختلف را برمی‌گرداند. برای مثال زمانی که یک کاربر وارد اپلیکیشن شد می‌توانیم از طریق متغیر user و متدهای دیگر به مشخصات این کاربر دسترسی پیدا کنیم. وضعیت مربوط به SignInButton، SignOutButton و SignUpButton نیز به صورت خودکار توسط خود Clerk مدیریت می‌شوند. حال با انجام این کارها، ما به صورت موفقیت آمیز، یک سیستم احراز هویت را به اپلیکیشن‌مان اضافه کردیم.

محافظت از روت‌ یا مسیرهای مختلف و انجام اعتبارسنجی

محتوای برخی از مسیرها و روت‌ها در اپلیکیشن تنها باید توسط افرادی که مراحل احراز هویت را پشت سر گذاشته‌اند دیده شوند، Clerk برای پیاده‌سازی چنین حالتی نیز امکاناتی در اختیار ما قرار داده که می‌توانیم از آن‌ها استفاده کنیم. یادتان باشد که بدون انجام چنین مواردی، سطح امنیت اپلیکیشن‌تان بسیار پایین خواهد آمد.

برای مخفی کردن یادداشت‌ها از کاربرانی که وارد وبسایت نشده‌اند ابتدا وارد Notes.tsx شوید و سپس useUser را از طریق @clerk/clerk-react به پروژه اضافه کنید. بعد از آن یک ثابت مانند زیر ایجاد کنید تا با سهولت بیشتر به این هوک دسترسی پیدا کنیم:

const { isSignedIn } = useUser();

حال می‌توانیم با استفاده از ثابت isSignedIn که یک مقدار بولین است سناریویی مانند زیر را پیاده‌سازی کنیم:

{
 isSignedIn ? (
  <>
   <h1 className="text-2xl">Create a New Note</h1>
   <NoteForm onCreate={handleNoteCreate} />
  </>
 ) : (
  <p className="text-2xl text-white">
   Create an account or log in to create a note.
  </p>
 );
}

همچنین برای مخفی کردن دکمه «حذف» از کاربرانی که وارد وبسایت نشده‌اند وارد فایل NoteItem.tsx شویم و useUser را نیز در این وارد کرده و مانند قطعه کد زیر، اپلیکیشن را بروزرسانی کنیم:

{
 isSignedIn && (
  <button
   className="bg-white hover:bg-gray-300 text-black py-1 px-3 rounded-lg"
   onClick={handleDelete}
  >
   Delete
  </button>
 );
}

حال اگر کاربری وارد وبسایت نشده باشد نمی‌تواند کاری در اپلیکیشن انجام دهد. اکنون نوبت آن است که برخی از مسیرها را نیز از دسترس همگان خارج کنیم. برای مثال قصد داریم یادداشت‌ها به جای آنکه در صفحه اصلی نمایش داده شوند به مسیر /notes بروند و هر کسی هم به این مسیر دسترسی نداشته باشد. ما تنها می‌خواهیم که صفحه اصلی برای کاربران قابل دیدن باشد. برای اینکار یک فایل جدید در دایرکتوری notes/page.tsx ایجاد کرده و کامپوننت Notes را از app/pages.tsx برداشته و به این قسمت اضافه کنید:

import Notes from "@/components/Notes";
import React from "react";
const NotePage = () => {
 return <Notes />;
};
export default NotePage;

Clerk با استفاده از یک Middleware به شما این امکان را می‌دهد تا بتوانید از مسیرها محافظت کنید و کاربرانی که وارد وبسایت نشده‌اند و درخواست دیدن یک مسیر محافظت شده را دارند به مسیرهای دیگری هدایت دهد. برای استفاده از این Middleware ما باید به صورت زیر عمل کنیم. از این طریق می‌توانیم مسیرهای عمومی و غیر عمومی را تعیین کنیم:

import { authMiddleware } from "@clerk/nextjs";
export default authMiddleware({
 publicRoutes: ["/"],
});
export const config = {
 matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],
};

برای مطالعه بیشتر در ارتباط با میدل ویر به لینک Clerk middleware مراجعه کنید.

در پایان

پیاده‌سازی یک روش امن برای سیستم احراز هویت یک مسئله بسیار حیاتی برای هر اپلیکیشنی است. از آنجایی که در فریمورک Next.js یک روش تمام و عیار برای این موضوع پیاده‌سازی نشده، ما امروز به شما Clerk را معرفی کردیم تا بتوانید این بخش از اپلیکیشن را به خوبی پیاده‌سازی بکنیم.

البته ویژگی‌های بسیار زیادی در Clerk وجود دارد که می‌توانید از آن‌ها نیز استفاده کنید. برای این موضوع می‌توانید سراغ مستندات رفته و با ویژگی‌های مختلف آن آشنا شوید.

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
5 از 1 رای

/@arastoo
ارسطو عباسی
کارشناس تولید و بهینه‌سازی محتوا

کپی رایتر، یوایکس رایتر، متخصص سئو محتوا و… عناوینی هستن که می‌تونم حرفه‌ام رو باهاشون خلاصه کنم اما جدای از این موارد، کتاب نوشتم، پادکست ضبط کردم، مارکتینگ محتوا انجام دادم و خلاصه تجربیات تا بخوایید در زمینه کلمات کسب کردم.

دیدگاه و پرسش

برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

ارسطو عباسی

کارشناس تولید و بهینه‌سازی محتوا