تعلم كيفية استخدام Next-Auth بخطوات بسيطة

سنتعلم معاً في هذا الدرس كيفة عمل صلاحيات تسجيل دخول بكل سهولة بإستخدام Next.js



السلام عليكم ورحمة الله وبركاته

سنتعلم في هذا الدرس كيفية عمل (authentication) صلاحيات تسجيل دخول المستخدم باستخدام Next.js 
سنقوم بإستخدام حزمة Next-Auth والتي بدورها ستسمح لنا عمل كل الصلاحيات بخطوات سهلة وبسيطة
سنقوم باستخدام تسجيل الدخول باستخدام المعرف وكلمة المرور وايضاً باستخدام جوجل 

النتيجة النهائية للدرس : 


الكود على Github (اضغط هنا)

متطلبات الدرس : 
  • المعرفة بأساسيات React.js & Next.js

ملاحظات : 
لن نقوم بشرح اساسيات جافاسكريبت و React.js & Next.js وغيرها من الأساسيات مثل شرح سطر الأومر وكيفية عمل الحزم وتثبيتها ...الخ حيث يتوجب عليك معرفة هذه الأمور قبل البدء في الدرس 

والآن دعونا نبدأ الدرس :

أولاً سنبدأ بتثبيت Next.js من خلال سطر الأوامر اكتب : 
npx create-next-app@latest

وهذا الأمر سيقوم بتنزيل اخر نسخة من Next.js 

النسخة التي تعمل لدي حالياً هي: 14.1.0

في حال اردت بتثبيت نسخة محددة قم بالتالي: 

npx create-next-app@14.1.0

للمزيد من المعلومات بأمكانك الأطلاع على الرابط التالي : 

https://nextjs.org/docs/getting-started/installation

الآن بعد كتابة الآمر سيقوم بسؤالك عدة اسئلة سنقوم بالأختيار كما يلي : 

  1. Project name : سيكون next-auth (بأمكانك اختيار اي اسم تريد)
  2. TypeScript? No
  3. Eslint? Yes
  4. Tailwind CSS? Yes
  5. `src/` directory?  No 
  6. App Router? Yes
  7. customize the default import alias? No
الآن سيقوم بتثبيت مشروع Next.js سننتظر حتى يقوم من الإنتهاء 
* كما تلاحظ قمنا باستخدام Tailwind CSS وهو اطار عمل بسيط يسمح لنا بتنسيق تطبيقنا عن طريق اضافة الكلاسات css فقط، إن لم تكن استخدمتها من قبل فلا داعي للقلق سأعطيك ملف CSS ققط قم بنسخها ولصقها كما هي 

بعد الأنتهاء من تثبيت Next.js سنقوم بتنزيل حزمة اضافية وهي حزمة Next-Auth باستخدام سطر الأوامر :
npm install next-auth

 قم بتشغيل المشروع عن طريق :
npm run dev 

الآن سنفتح المشروع عن طريق محرر الأكواد الخاص بك وقم بأنشاء الملف التالي : 
api/auth/[...nextauth]/route.js

لا بد من انشاء هذا الملف كما قمت بكتابته وإلا لن تعمل معك حزمة Next-auth 

بأمكانك الأطلاع على المزيد من المعلومات من خلال الرابط التالي : 

في البداية سنقوم بتسجيل الدخول بأستخدام كل من المعرف و كلمة المرور
ولعمل ذلك قم بالذهاب إلى الملف route.js وقم بإضافة الكود التالي: 

import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"

export const authOptions = {
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        identifire: {
          label:
            "Identifire", type: "text",
          placeholder: "Your username or email"
        },
        password: {
          label: "Password",
          type: "password"
        }
      },
      async authorize(credentials, req) {
        console.log('credentials: ', credentials)
        const profilePicture = "https://gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50?size=100"

        const user = {
          id: "1",
          name: credentials.identifire,
          image: profilePicture
        }

        if (user) {
          return user
        } else {
         
          return null
          
        }
      }
    })

  ],
}

const handler = NextAuth(authOptions)

export { handler as GET, handler as POST }

  
كما نلاحظ هنا في البداية قمنا باستيراد NextAuth من حزمة next-auth 
وبعدها ايضاً ومن نفس الحزمة قمنا باستيراد CredentialsProvider وهذا هو المزود الذي سيسمح بتسجيل الدخول باستخدام كل من المعرف وكلمة المرور وهناك العديد من المزودات والتي يرمز لها بالـ provider مثل Google - Github - Twitter - Facebook ... etc 
للمزيد من المعلومات عنها قم بزيارة الرابط التالي : 

بعد ذلك لدينا authOptions وهو عبارة عن اوبجيكت باضافة الـ providers والتحكم بها  
في البداية بداخل هذا الاوبجيكت لدينا providers وهو عبارة عن مصفوفة سنقوم بدخلها بتعريف جميع الـ providers التي ستحتاجها في مشروعك سواء كان جوجل أو github او credentials 

والآن لنستطيع تسجيل الدخول باستخدام المعرف وكلمة المروف سنحتاج لاضافة CredentialsProvider بداخل مصفوفتنا 

بداخل CredentialsProvider سنقوم ايضاً باضافة عدة خيارات : 
1- name: وهو الاسم 
2- credentials : وهنا حيث سنعرف الحقول الازمة التي سيقوم المستخدم بملئها من اجل تسجيل الدخول، وفي حالتنا نريد المعرف وكلمة المرور ولذلك كما تلاحظ قمنا بأضافة كل من identifire & password 

ان اردت بأمكانك تغيير identifire بـ username أو email على سبيل المثال ولكن في هذا الدرس قررت جعلها identifire بمعنى المعرف أي يستطيع المستخدم الدخول باستخدام اسم المستخدم أو البريد الإلكتروني، وطبعاً ذلك قد يختلف حسب حاجة التطبيق الذي تعمل عليه والخيارات التي تريد توفيرها في تطبيقك 

الآن بعد ذلك لدينا كل من label - type - placeholder وطبعاً من تسمياتها تستطيع ان تستنتج بأنها خيارات الحقول التي سيملئها المستخدم عند عملية تسجيل الدخول، تستطيع التغيير فيها ايضاً بحسب ما تراه مناسباً لك ولمشروعك 

الآن من خلال المتصفح اذهب الى الرابط التالي: 

النتيجة : 



كما ترى قام next-auth بعمل كل شيء من صفحة الدخول إلى وحقول وزر الإدخال  بشكل تلقائي 

وقبل أن نقوم بالتجربة دعنا نقوم بشرح بقية الكود اعلاه 
حالياً كل ما تبقى لدينا هو الدالة authorize وهنا حيث سيقوم next-auth بتولي عملية تسجيل الدخول بعد الضغط على زر تسجيل الدخول 

طبعاً في العادة هنا حيث سنقوم بمقارنة البيانات المرسلة بما لديك في قاعدة  البيانات ومن ثم ستقوم بجلب بيانات المستخدم من قاعدة البيانات وارسالها 

ولكن نحن هنا لن نقوم باستخدام هذه الخطوة حيث سنقوم فقط بأخذ المعلومات المدخلة من قبل المستخدم وتسجيل الدخول بشكل تلقائي بما أننا نقوم هنا فقط بشرح وتوضيح كيفة عمل next-auth وربما سيكون اختبار جيد بالنسبة لك أن تقوم بإدراج قاعدة بيانات والعمل بها 

حسنا كما موضح لنا في الكود اعلاه أن الدالة authorize تأخذ المعامل credentials وهذا المعامل يقوم بحمل البيانات التي ادخلها المستخدم 

بمعنى تستطيع الوصول للمعرف عن طريق credentials.identifire ان كنت استخدمت username أو email ستقوم بالوصل اليه عن طريق identifire.username أو identifire.email 

الآن بعد ذلك سأقوم بعمل المتغير user وقمنا باضافة معلومات المستخدم بداخلها (يفترض أن تكون بيانات المستخدم من قاعدة البيانات)

طبعاً كما ترى قمت بإضافة profilePicture وهي فقط صورة افتراضية قمت بإضافتها للمستخدم تستطيع تغييرها بأي صورة اخرى إن اردت 

حسنا الآن لدينا كل ما يلزم لتسجيل الدخول واظهار معلومات المستخدم داخل تطبيقنا حيث ستستطيع الوصل إلى معلومات المستخدم من خلال next-auth hook (useSession())

ولنفعل ذلك الآن دعنا نتجه الى ملف app/page.js حيث سنقوم بتجربة ذلك ...

ولكن قبل ذلك سنحتاج لفعل خطوة اخرى وهي أن نقوم بتغليف تطبيقننا بـ <SessionProvider> حتى نستطيع الوصل إلى useSession

ولعمل ذلك سنقوم بإنشاء ملف providers/AuthProvider.js  في المسار الرئيسي للتطبيق وقم بإضافة الكود التالي: 
 
"use client"

import { SessionProvider } from "next-auth/react";

const AuthProvider = ({children}) => {
  return (
    {children}
  )
}

export default AuthProvider

 


يجب اضافة "use client" اعلى الصفحة وإلا ستتحصل على خطأ 

الآن سنذهب إلى ملف app/layout.js وسنقوم بتغليف تطبيقنا بـ AuthProvider حتى نستطيع استخدام useSession() من أي مكان في التطبيق 

حيث سيكون ملف layout.js كما في التالي : 
   
import { Inter } from "next/font/google";
import "./globals.css";
import AuthProvider from "@/providers/AuthProvider";
import Link from "next/link";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Auth Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <AuthProvider>
          <Link href="/" className="text-lg">Home</Link>
          <main className="main">
            <h1 className="text-2xl mb-10">Next Auth</h1>
            {children}
          </main>
        </AuthProvider>
      </body>
    </html>
  );
}

   
هنا قمت بأضفة العنصر main فقط كخطوة تنسيقية لا اكثر 

الآن كخطوة اخرى من اجل تنسيق التطبيق اريد منك الذهاب إلى ملف app/globals.css وتقوم باستبدال محتوياته بالكود التالي : 
@tailwind base; @tailwind components; @tailwind utilities; @layer components { :root { @apply p-10 h-[100vh] overflow-hidden flex flex-col justify-center text-zinc-800 bg-[#ececec]; } .main { @apply h-[400px] bg-white p-5 flex flex-col items-center justify-center mt-2 rounded-[2rem]; } .btn { @apply drop-shadow px-10 py-3 rounded-lg; } .btn-primary { @apply bg-white hover:bg-gray-200 text-black; } .google { @apply text-2xl font-bold text-rose-600; } .avatar { @apply rounded-full drop-shadow-lg my-5; } }
الآن سنعود لنكمل العمل على ما تبقى من next-auth حتى نستطيع اظهار بيانات المستخدم ...

اذهب الآن إلى ملف app/page.js وقم بحذف جميع محتويات الملف واضف الكود التالي: 
'use client'
import Image from "next/image"

import { signIn, signOut, useSession } from "next-auth/react"
import Link from "next/link"

export default function Home() {
  const { data: session, status } = useSession()
  console.log(session)

  return (
    <div>
      {session ?
        <div className="flex flex-col items-center ">
          <p className="">welcome {session.user?.name}</p>

          <Image
            priority={true} // Change this line
            src={session?.user?.image}
            alt="image"
            width={100}
            height={100}
            className="avatar"
          />
          <button
            className="btn btn-primary"
            onClick={() => signOut()}>
            Signout
          </button>
        </div>
        :
        <div className="flex flex-col items-center">
          <Link
            href='/api/auth/signin'
            className="btn btn-primary mb-5"
          >
            Sign in
          </Link>

          <button
            onClick={() => signIn('google')}
            className="btn btn-primary"
          >
            <span className="google">G </span>Sign in with google
          </button>
          

        </div>
      }
    </div>
  )
}

الآن ان توجهت للصفحة الرئيسة ستحصل على الخطأ  Invalid src prop 
هذه احدى الأخطاء التي قد تظهر عند استخدام next/image حيث يتوجب عليك تعريف المضيف في ملف next.config
لمزيد من المعلومات زر الرابط التالي : 
ولحل هذه المشكلة سنتجه لملف next.config.mjs 
  
const nextConfig = {
    images: {
        domains: [
             "lh3.googleusercontent.com",
             "gravatar.com"
            ],
    }
};

  
لقد قمت ايضاً بإضافة lh3.googlegoogleusercontent.com لاننا سنحتاجه فيما بعد عندما نقوم بعمل تسجيل الدخول باستخدام جوجل لعرض صورة الملف الشخصي

الآن دعنا نعود لملف app/page.js ان القيت نظرة على الكود فلا اعتقد بأنك ستواجه مشكلة في فهم الكود، ولكن ما يهمنا هنا هو  useSession() وهذا هو الهوك الذي يقدمه لنا Next.js من اجل التحقق والوصول الى بيانات المستخدم ومعرفة ما إذا كان المستخدم قيد تسجيل الدخول أم لا 

كما ترى ايضا قمنا باستخدام const { data: session, status } = useSession()

الآن نستطيع بكل بساطة أن نصل إلى بيانات المستخدم في حال كان قيد تسجيل الدخل باستخدام session?.user او حتى معرفة حالة المستخدم إن كان قيد تسجيل الدخول ام لا باستخدام status جرب طباعة المتغيير في الكونسول لرؤية النتيجة 

ملاحظة: في حال لم يكن هناك مستخدم فقيمة session ستكون null و status ستكون unauthenticated 

ايضاً كما تشاهد قمت بإضافة زر تسجيل الدخول عن طريق جوجل لنتجاهله حالياً وسنعود اليه لاحقاً 

يهمنا ايضاً زر تسجيل الخروج حيث توفر لنا next-auth الدالة signOut لتسجيل الخروج بكل سهولة سنقوم بتجربتها بعد ان نقوم بتسجيل الدخول 

الآن قم بالضغط على رز Sign in وقم بعمل بتجربة عملية تسجيل الدخول وبعدها توجه للصفحة الرئيسية 

النتيجة :


الآن كما تشاهد مبروك لقد قمت بعملية تسجيل الدخول بشكل سليم وبطريقة سهلة وسريعة جداً بفضل next-auth

دعنا نقوم الآن بتسجيل الدخول باستخدام جوجل ...

في الواقع عملية التسجيل باستخدام جوجل بـ next-auth اسهل واسرع بكثير من تسجيل الدخول باستخدام credentials

ولكن قبل ذلك هناك خطوة مزعجة نوعاً ما وهي انشاء تطبيق عن طريق جوجل والحصل على client id و secret id لذلك يجب علينا فعلها 

ولعمل ذلك سنتجه لموقع  cloud.google عن طريق الرابط التالي : 

وقم باتباع الخطوات التالية : 

1- قم بتسجيل الدخول ومن ثم من في اعلى القائمة اضغط على console 




2- الآن اضغط على زر الاسقاط في اعلى الصفحة وقم باختيار New Project



3- قم بادخال البيانات الازمة ثم اضغط على create 

4- ستنتظر قليلاً حتى يقوم جوجل بعمل التطبيق ثم ستعود من جديد وتضغط على زر الاسقاط وتختار التطبيق الذي قمت بإنشائه 


5- الآن اذهب الى APIs & Services وبعدها في الصفحة التالية من القائمة اختر OAuth consent screen قم باختيار External ثم اضغط create

6- الآن سنقوم بملئ بيانات App information (الحقول التي عليها علامة * حمراء اجبارية) سنتجاهل بقية الحقول الغير مهمة من اجل اختصار الوقت في الشرح
* App name => ادخل اسم التطبيق
* User support email => قم بإدخال ايميلك الشخصي 
* authorized domains => ADD DOMAIN 
* Developer contact information => ادخل بريدك الالكتروني
* SAVE AND CONTINUE 
* الآن بقية الصفحات سنقوم فقط بالضغط على SAVE AND CONTINUE فقط 

7- الآن سنعود مرة اخرى الى APIs & Services وسنقوم من القائمة الجانبية باختيار Credentials ثم من اعلى الصفحة اضغط على CREATE CREDENTIALS ثم اختر OAuth client ID 
الآن سنقوم ببعض الخطوات 
* Application type => Web application
* Name => YOUR_APP_NAME
* Authorized JavaScript origins => ADD URI => http://localhost:3000
* Authorized redirect URIs => ADD URI => http://localhost:3000/api/auth/callback/google
*الآن قم بحفظ التغيرات 

*ملاحظة هذه الخطوة مهمة جداً وإلا لن يسمح لك جوجل بالوصل الى التطبيق 

8- الآن سيقوم جوجل باعطائك كل من Client ID & Client secret قم بحفظ هذه البيانات لأننا سنحتاجها من اجل عملية تسجيل الدخول 

الآن دعنا نعود الى تطبيقنا على Next.js وقم بأنشاء الملف .env بداخله سنقوم بإدخال المعلومات التالية : 

GOOGLE_ID=YOUR_CLIENT_GOOGLE_ID
GOOGLE_SECRET=YOUR_GOOGLE_SECRET

قم باستبدال كل من YOUR_CLIENT_GOOGLE_ID & YOUR_GOOGLE_SECRET بالقيم الخاصة بك 

الآن سنعود الى ملف route.js الخاص بنا وفي اعلى الصفحة قم باستدعاء Google Provider كما في التالي : 

import GoogleProvider from "next-auth/providers/google"

الآن سنقوم بتعريف ذلك بداخل authOptions كما في التالي :
export const authOptions = {
  providers: [
     GoogleProvider({
         clientId: process.env.GOOGLE_ID,
         clientSecret: process.env.GOOGLE_SECRET,
     }),
     ...
 
   
     
بعد فعل هذا مبارك عليك اصبح تطبيقك يدعم تسجيل الدخول عبر جوجل بشكل تلقائي 
دعنا نذهب لصفحة تسجيل الدخول الخاصة بنا وانظر الى النتيجة...
كما ترى اصبح لدينا زر تسجيل الدخول عبر جوجل الآن لو قمت باضغط على الزر يفترض ان تتمكن من تسجيل الدخول باستخدام جوجل

الآن بنفس الطريقة يمكنك استخدم تسجيل الدخول باستخدام اي مزود آخر مثل Github - Facebook - Twitter وغيرها الكثير بأمكانك الإطلاع على الرابط التالي لمزيد من المعلومات : 

الآن لنلقي نظرة على الصفحة الرئيسية بعد تسجيل الدخول باستخدام جوجل :

كما تشاهد لدينا معلومات المستخدم وصورة الملف الشخصي اذاً مبارك عليك تمكنت الدخول باستخدام جوجل بهذه السهولة 
الآن لو عدت للملف app/page.js تتذكر بأننا قمنا بعمل زر للدخول باستخدام جوجل 
الآن لو سجلت الخروج وجربت استخدام هذا الزر ستتمكن ايضاً من الدخول باستخدام جوجل وذلك لأن next-auth يقدم لنا الدالة signIn('google') لتسجيل الدخول بسهولة كل ما عليك تمرير اسم provider بداخل الدالة signIn كمعامل سواء كان جوجل أو فيس بوك أو غيرها من المزودات وستتمكن من تسجيل الدخول بسهولة 

الآن وصلنا إلى نهاية الدرس وهذا الكود النهائي لتطبيقنا : 
التطبيق على Github (اضغط هنا)

//app/layout.js
import { Inter } from "next/font/google";
import "./globals.css";
import AuthProvider from "@/providers/AuthProvider";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Auth Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <AuthProvider>
          <main className="main">
            <h1 className="text-2xl mb-10">Next Auth</h1>
            {children}
          </main>
        </AuthProvider>
      </body>
    </html>
  );
}

//api/auth/[...nextauth]/route.js
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import CredentialsProvider from "next-auth/providers/credentials";

export const authOptions = {
  providers: [
    GoogleProvider({
        clientId: process.env.GOOGLE_ID,
        clientSecret: process.env.GOOGLE_SECRET,
    }),
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        identifire: {
          label:"Identifire", 
          type: "text",
          placeholder: "Your username or email"
        },
        password: {
          label: "Password",
          type: "password"
        }
      },
      async authorize(credentials, req) {
        console.log('credentials: ', credentials)
        const profilePicture = "https://gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50?size=100"
        const user = {
          id: "1",
          name: credentials.identifire,
          image: profilePicture
        }

        if (user) {
          return user
        } else {
          return null
        }
      }
    })

  ],
}

const handler = NextAuth(authOptions)

export { handler as GET, handler as POST }
//app/page.js

'use client'
import Image from "next/image"

import { signIn, signOut, useSession } from "next-auth/react"
import Link from "next/link"

export default function Home() {
  const { data: session, status } = useSession()
  console.log(session)

  return (
    <div>
      {session ?
        <div className="flex flex-col items-center ">
          <p className="">welcome {session.user?.name}</p>

          <Image
            priority={true} // Change this line
            src={session?.user?.image}
            alt="image"
            width={100}
            height={100}
            className="avatar"
          />
          <button
            className="btn btn-primary"
            onClick={() => signOut()}>
            Signout
          </button>
        </div>
        :
        <div className="flex flex-col items-center">
          <Link
            href='/api/auth/signin'
            className="btn btn-primary mb-5"
          >
            Sign in
          </Link>

          <button
            onClick={() => signIn('google')}
            className="btn btn-primary"
          >
            <span className="google">G </span>Sign in with google
          </button>
          

        </div>
      }
    </div>
  )
}
//providers/AuthProvider.js
"use client"

import { SessionProvider } from "next-auth/react";

const AuthProvider = ({children}) => {
  return (
    {children}
  )
}

export default AuthProvider

ليست هناك تعليقات

المقالات الاكثر مشاهدة

قالب هاش تك 2016 © - منتج إبداعي طور بواسطة حيّاك