برنامه نویسی

احراز هویت مبتنی بر نقش با استفاده از Nextauth و next.js

Summarize this content to 400 words in Persian Lang
سلام، بنابراین اگر شما هم در مورد متحد تاریک اینترنت جستجوی راه‌حل‌های Auth و نقش‌های خودتان فکر می‌کردید، اما نتوانستید چیزی را پیدا کنید یا شاید هم پیدا کردید، دیگر کار نمی‌کند، پس در مکان مناسبی با این ویژگی هستید. کد من نسخه بسته ها را نیز می دهم تا برای شما راحت تر باشد.

اکنون اجازه دهید ابتدا تمام بسته های مورد نیاز خود را نصب کنیم

npm install next-auth@beta
npm install drizzle-orm zod react-hook-form

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا بیایید ارائه دهندگان auth را برای nextAuth تنظیم کنیم که یک فایل در ما ایجاد می کند

lib/auth/index.ts

در این فایل ما از ارائه‌دهنده credentails استفاده می‌کنیم زیرا به‌طور پیش‌فرض OAuth هیچ نقشی را به ما باز نمی‌گرداند، اما همچنین نحوه استفاده از oAuth برای اختصاص نقش‌ها را خواهیم دید.

export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: DrizzleAdapter(db),
providers: [
Credentials({
name: “credentials”,
credentials: {
email: {
type: “email”,
label: “Email Address”,
placeholder: “Email Address”,
},
password: {
type: “password”,
label: “Password”,
},
},
async authorize(credentials) {
const { email, password } = await signInSchema.parseAsync(credentials);

const user = await db
.select()
.from(users)
.where(eq(users.email, email))
.execute()
.then((res) => res[0]);

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

const isValidPassword = await bcryptjs.compare(password, user.password);

if (!isValidPassword) return null;

return {
id: user.id,
name: user.name,
email: user.email,
};
},
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,

profile(profile: GoogleProfile) {
return { …profile, role: “user” };
},
})
],
});

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شاید زمان خوبی باشد که بگوییم من از postgres و drizzle ORM برای ذخیره و بازیابی این اطلاعات از DB استفاده می کنم.

ما از آداپتور drizzle برای آن استفاده می کنیم که می توانید آن را با استفاده از آن نصب کنید

npm install drizzle-orm @auth/drizzle-adapter
npm install drizzle-kit –save-dev

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شما می توانید طرح مناسب بارانی را در لینک اینجا پیدا کنید تا مجوز کار کند. اکنون فقط باید از این هندلر در مسیرهای api استفاده کنیم تا کار کند.

import { handlers } from “@/lib/auth”;

export const { GET, POST } = handlers;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در حال حاضر auth کار می کند اما هنوز نقشی وجود ندارد. ابتدا طرح drizzle و سپس گزینه های nextAuth خود را تغییر می دهیم.

به یاد داشته باشید که این می تواند یک فیلد ساده به عنوان نقش در جدول کاربران باشد که دارای یک مقدار رشته است. اما من آن را به این شکل ساختم تا بتوانم هر تعداد نقشی که می خواهم بسازم و به آن مجوز اضافه کنم

export const roles = pgTable(“roles”, {
id: text(“id”)
.primaryKey()
.$defaultFn(() => createId()),
name: text(“name”).notNull(),
description: text(“description”),
});

export const permissions = pgTable(“permissions”, {
id: text(“id”)
.primaryKey()
.$defaultFn(() => createId()),
name: text(“name”).notNull(),
description: text(“description”),
});

export const rolePermissions = pgTable(“role_permissions”, {
roleId: text(“roleId”).references(() => roles.id, { onDelete: “cascade” }),
permissionId: text(“permissionId”).references(() => permissions.id, {
onDelete: “cascade”,
}),
});

export const userRoles = pgTable(“user_roles”, {
userId: text(“userId”).references(() => users.id, { onDelete: “cascade” }),
roleId: text(“roleId”).references(() => roles.id, { onDelete: “cascade” }),
});

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون باید NextAuthOption را تغییر دهیم تا نقش‌ها و مجوزها در جلسه کاربر گنجانده شوند.

ابتدا توابع پاسخ به تماس را برای دریافت نقش ها تعریف می کنیم.

callbacks: {
async jwt({ token, user }) {
if (user && user.id) {
const { role, permissions } = await getUserRoleAndPermissions(user.id);
token.role = role;
token.permissions = permissions;
}
return token;
},
async session({ session, token }) {
if (token && session.user) {
session.user.id = token.id;
session.user.role = token.role;
session.user.permissions = token.permissions;
}
return session;
},
},

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

تابع getRolesandPermission دقیقاً همانطور که به نظر می رسد از drizzle برای درخواست نقش ها و مجوز از db استفاده می کند. به‌طور پیش‌فرض این به تنهایی کار نمی‌کند، ما همچنین باید تغییراتی در انواع ایجاد کنیم.

declare module “next-auth” {
interface Session {
user: {
id: string;
role: string;
permissions: string[];
} & DefaultSession[“user”];
}
}

declare module “next-auth/jwt” {
interface JWT {
id: string;
role: string;
permissions: string[];
}
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون با دسترسی به جلسه می توانیم نقش ها و مجوزها را دریافت کنیم. و با استفاده از این می توانید کاربر را در سطح صفحه مسدود کنید یا با استفاده از میان افزار کل گروه مسیری که می توانید محافظت کنید.

این روش می تواند در یک Sass چند مستاجر واقعاً مفید باشد زیرا نمی خواهید کاربر خود را در جای دیگری ذخیره کنید این یک راه حل عالی است. برای مطالعه این مطلب از شما سپاسگزارم

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

اکنون اجازه دهید ابتدا تمام بسته های مورد نیاز خود را نصب کنیم

  npm install next-auth@beta
  npm install drizzle-orm zod react-hook-form
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا بیایید ارائه دهندگان auth را برای nextAuth تنظیم کنیم که یک فایل در ما ایجاد می کند

lib/auth/index.ts

در این فایل ما از ارائه‌دهنده credentails استفاده می‌کنیم زیرا به‌طور پیش‌فرض OAuth هیچ نقشی را به ما باز نمی‌گرداند، اما همچنین نحوه استفاده از oAuth برای اختصاص نقش‌ها را خواهیم دید.

  export const { handlers, signIn, signOut, auth } = NextAuth({
 adapter: DrizzleAdapter(db),
  providers: [
    Credentials({
      name: "credentials",
      credentials: {
        email: {
          type: "email",
          label: "Email Address",
          placeholder: "Email Address",
        },
        password: {
          type: "password",
          label: "Password",
        },
      },
      async authorize(credentials) {
        const { email, password } = await signInSchema.parseAsync(credentials);

        const user = await db
          .select()
          .from(users)
          .where(eq(users.email, email))
          .execute()
          .then((res) => res[0]);

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

         const isValidPassword = await bcryptjs.compare(password, user.password);

         if (!isValidPassword) return null;

        return {
          id: user.id,
          name: user.name,
          email: user.email,
        };
      },
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,

      profile(profile: GoogleProfile) {
        return { ...profile, role: "user" };
      },
    })
  ],
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شاید زمان خوبی باشد که بگوییم من از postgres و drizzle ORM برای ذخیره و بازیابی این اطلاعات از DB استفاده می کنم.

ما از آداپتور drizzle برای آن استفاده می کنیم که می توانید آن را با استفاده از آن نصب کنید

npm install drizzle-orm @auth/drizzle-adapter
npm install drizzle-kit --save-dev
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شما می توانید طرح مناسب بارانی را در لینک اینجا پیدا کنید تا مجوز کار کند. اکنون فقط باید از این هندلر در مسیرهای api استفاده کنیم تا کار کند.

import { handlers } from "@/lib/auth";

export const { GET, POST } = handlers;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در حال حاضر auth کار می کند اما هنوز نقشی وجود ندارد. ابتدا طرح drizzle و سپس گزینه های nextAuth خود را تغییر می دهیم.

به یاد داشته باشید که این می تواند یک فیلد ساده به عنوان نقش در جدول کاربران باشد که دارای یک مقدار رشته است. اما من آن را به این شکل ساختم تا بتوانم هر تعداد نقشی که می خواهم بسازم و به آن مجوز اضافه کنم

export const roles = pgTable("roles", {
  id: text("id")
    .primaryKey()
    .$defaultFn(() => createId()),
  name: text("name").notNull(),
  description: text("description"),
});

export const permissions = pgTable("permissions", {
  id: text("id")
    .primaryKey()
    .$defaultFn(() => createId()),
  name: text("name").notNull(),
  description: text("description"),
});

export const rolePermissions = pgTable("role_permissions", {
  roleId: text("roleId").references(() => roles.id, { onDelete: "cascade" }),
  permissionId: text("permissionId").references(() => permissions.id, {
    onDelete: "cascade",
  }),
});

export const userRoles = pgTable("user_roles", {
  userId: text("userId").references(() => users.id, { onDelete: "cascade" }),
  roleId: text("roleId").references(() => roles.id, { onDelete: "cascade" }),
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون باید NextAuthOption را تغییر دهیم تا نقش‌ها و مجوزها در جلسه کاربر گنجانده شوند.

ابتدا توابع پاسخ به تماس را برای دریافت نقش ها تعریف می کنیم.

 callbacks: {
    async jwt({ token, user }) {
      if (user && user.id) {
        const { role, permissions } = await getUserRoleAndPermissions(user.id);
        token.role = role;
        token.permissions = permissions;
      }
      return token;
    },
    async session({ session, token }) {
      if (token && session.user) {
        session.user.id = token.id;
        session.user.role = token.role;
        session.user.permissions = token.permissions;
      }
      return session;
    },
  },
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

تابع getRolesandPermission دقیقاً همانطور که به نظر می رسد از drizzle برای درخواست نقش ها و مجوز از db استفاده می کند. به‌طور پیش‌فرض این به تنهایی کار نمی‌کند، ما همچنین باید تغییراتی در انواع ایجاد کنیم.

declare module "next-auth" {
  interface Session {
    user: {
      id: string;
      role: string;
      permissions: string[];
    } & DefaultSession["user"];
  }
}

declare module "next-auth/jwt" {
  interface JWT {
    id: string;
    role: string;
    permissions: string[];
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون با دسترسی به جلسه می توانیم نقش ها و مجوزها را دریافت کنیم. و با استفاده از این می توانید کاربر را در سطح صفحه مسدود کنید یا با استفاده از میان افزار کل گروه مسیری که می توانید محافظت کنید.

این روش می تواند در یک Sass چند مستاجر واقعاً مفید باشد زیرا نمی خواهید کاربر خود را در جای دیگری ذخیره کنید این یک راه حل عالی است. برای مطالعه این مطلب از شما سپاسگزارم

نوشته های مشابه

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

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

دکمه بازگشت به بالا