اذهب إلى المحتوى

السؤال

نشر

السلام عليكم.

أرجو مساعدتي في التحقق من البيانات بواسطة cookie و jwt في مشروع Nextjs 14.

تظهر لي رسالة الخطأ التالية

{
    "message": "Not authorized, no token"
}

للتوضيح:

في البداية قمت بتوليد token و cookie

utils/generateToken

import jwt from 'jsonwebtoken'

const generateToken = (id) => {
    const token = jwt.sign({ userId: id }, process.env.JWT_SECRET, {
        expiresIn: '1d'
    });

    return token;
}

const setTokenCookie = (response, token) => {
    response.cookies.set('token', token, {
        httpOnly: true,
        secure: process.env.NODE_ENV !== 'development',
        sameSite: 'strict',
        maxAge: 60*60*24
    });
}

export { generateToken, setTokenCookie };

ثم قمت بإنشاء الحساب وتسجيل الدخول (سوف أعرض تسجيل الدخول لأنهما مشابهين كثيرا)

app/api/auth/login/route.js

import connectDB from "@/config/connectDB";
import User from "@/models/User";
import { generateToken, setTokenCookie } from "@/utils/generateToken";
import bcrypt from "bcryptjs";
import { NextResponse } from "next/server";

/**
 *  Method: POST
 *  route : /api/auth/login
*/
export const POST = async (request) => {
    await connectDB();
    try {
      const { email, password } = await request.json();
  
      const user = await User.findOne({ email });
      const isMatch = await bcrypt.compare(password, user.password)
      
      if (!user || !isMatch) {
        return new NextResponse("Invalid Credentials", { status: 400 })
      } 
  
      if (user) {
        const token = generateToken(user._id);
        const response = new NextResponse(
          JSON.stringify({ user: user.email }),
          { status: 200 }
        );
        setTokenCookie(response, token);
        return response;
      } else {
        return new NextResponse("Failed to create user", { status: 500 });
      }
    } catch (error) {
      console.log(error);
      return new Response("Something went wrong => Register User", {
        status: 500,
      });
    }
  };

ثم قمت بتحديد الوسائط

middlewares/protect.js

import User from "@/models/User";
import { cookies } from "next/headers";

const protect = async (request) => {
    const cookieStore = cookies()
    const token = cookieStore.get('jwt')?.value;
  
    if (!token) {
      throw new Error('Not authorized, no token');
    }
  
    try {
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      const user = await User.findById(decoded.userId)
  
      if (!user) {
        throw new Error('Not authorized, user not found');
      }
  
      return user;
    } catch (error) {
      console.error(error);
      throw new Error('Not authorized, token failed');
    }
  };
  
  export default protect;

في النهاية لتجربة التحقق قمت ب:

app/api/auth/me/route.js

import connectDB from "@/config/connectDB"
import protect from "@/middleware/protect"
import User from "@/models/User"
import { NextResponse } from "next/server"

/**
 *  Test If Route Is Protected
*/
export const GET = async (request) => {
    await connectDB()
    try {
        const user = await protect(request)

        const me = await User.findById(user._id )

        return NextResponse.json(me, { status: 200 })
    } catch (error) {
        return NextResponse.json({ message: error.message }, { status: 401 });
    }
}

الرجاء مساعدتي في تحديد سبب فشل التحقق من البيانات. شكرا.

Recommended Posts

  • 0
نشر

المشكلة في middlewares/protect.js في هذا السطر 

const token = cookieStore.get('jwt')?.value;

حيث تريد الوصول للكوكيز باسم jwt وهي غير موجودة لأنك في utils/generateToken عند وضع الكوكيز كانت باسم token وليس jwt

response.cookies.set('token', token, {
                      ^^^^^
        httpOnly: true,
        secure: process.env.NODE_ENV !== 'development',
        sameSite: 'strict',
        maxAge: 60*60*24
});

لذا نقوم بتعديل هذا السطر في middlewares/protect.js ليصبح ليتم الوصول للكوكيز بشكل صحيح

const token = cookieStore.get('token')?.value;

وأيضا قم باستيراد الحزمة jwt أعلى ملف middlewares/protect.js ليتم الوصول منها للدالة ()verify حيث أننا ننريدها ليتم فك تشفير token بعد ذلك.

import jwt from 'jsonwebtoken'

بالتوفيق...

  • 0
نشر

بناء على الشيفرة خاصتك، ففي ملف generateToken.js، تقوم بتعيين اسم الـ cookie كـ 'token' هنا:

response.cookies.set('token', token, {
});

لكن في ملف protect.js، تحاول الحصول على الـ cookie باسم 'jwt':

const token = cookieStore.get('jwt')?.value;

لذا يجب أن يكون اسم الـ cookie متطابقاً في كلا الموضعين.

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

import jwt from 'jsonwebtoken';

أما فيما يخص كيفية التعامل مع الـ response في ملف generateToken.js ففي الدالة setTokenCookie، تستخدم response.cookies.set، لكن في Next.js 14، يجب استخدام cookies() من next/headers كالتالي:

import { cookies } from 'next/headers';

const setTokenCookie = (token) => {
    cookies().set('token', token, {
        httpOnly: true,
        secure: process.env.NODE_ENV !== 'development',
        sameSite: 'strict',
        maxAge: 60*60*24
    });
}

أما في ملف login/route.js، يجب تعديل كيفية استخدام setTokenCookie إلى:

if (user) {
    const token = generateToken(user._id);
    setTokenCookie(token);
    return NextResponse.json({ user: user.email }, { status: 200 });
} else {
    return new NextResponse("Failed to create user", { status: 500 });
}

واحرص على أن تكون قمت بتعريف ال JWT_SECRET في ملف .env، أرجو تصحيح الأخطاء التالية مع إرفاق صورة للخطأ الذي تواجهه في حالة استمرار المشكلة.

  • 0
نشر
بتاريخ 9 دقائق مضت قال Mustafa Mahmoud7:

المشكلة في middlewares/protect.js في هذا السطر 

const token = cookieStore.get('jwt')?.value;

حيث تريد الوصول للكوكيز باسم jwt وهي غير موجودة لأنك في utils/generateToken عند وضع الكوكيز كانت باسم token وليس jwt

response.cookies.set('token', token, {
                      ^^^^^
        httpOnly: true,
        secure: process.env.NODE_ENV !== 'development',
        sameSite: 'strict',
        maxAge: 60*60*24
});

لذا نقوم بتعديل هذا السطر في middlewares/protect.js ليصبح ليتم الوصول للكوكيز بشكل صحيح

const token = cookieStore.get('token')?.value;

وأيضا قم باستيراد الحزمة jwt أعلى ملف middlewares/protect.js ليتم الوصول منها للدالة ()verify حيث أننا ننريدها ليjم فك تشفير token بعد ذلك.

import jwt from 'jsonwebtoken'

بالتوفيق...

مارأيك بطريقة كتابة الكود. هل تخضع لbest practice

  • 0
نشر
بتاريخ 25 دقائق مضت قال محمود سعداوي2:

مارأيك بطريقة كتابة الكود. هل تخضع لbest practice

بنسبة كبيرة نعم فأنت تقوم بالأتي:-
1- تقسيم الكود الخاص بك إلى دوال صغيرة ليسهل التعامل معها.
2- التعامل مع الأخطاء وإرسال رسالة بالخطأ في كل جزء يسهل العملية أيضا.
3 -إرسال كود حالة مثل (200 ، 500، 201) جيدا أيضا.
4-طريقة التسمية وكل شئ يقوم بما تم تسميته به جيد.
5- كتباتك لتوثيق الدالة مثل هذا جيد ضعه لكل الدوال أيضا.

/**
 *  Method: POST
 *  route : /api/auth/login
 *  
*/

استمر على هذا النهج ومع الوقت ستتطور أكثر وأكثر.

بالتوفيق..

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...