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

كيف اضع bearer token في Authorization في js fetch api

السؤال

نشر (معدل)

جالس اتعلم استخدم laravel sanctum للتحقق و لكن اريد ان احصل bearer token الخاص بالمستخدم لارسال البيانات.

هل اعمل fetch api يأخذ bearer token الخاص بالمستخدم الذي يكون مخزن في session او هناك طريقة اخرى احصل عليه و اضعه في authorization header ؟

انا اريد استخدامه ليس في postman بل في موقع الكتروني عادي بستخدام fetch لان اذا استخدم auth:snctum يظهر لي unauthnticated لان bearer token ليس موجود في header كيف اجيب bearer token و اضعه header?

تم التعديل في بواسطة Zerious San

Recommended Posts

  • 0
نشر (معدل)

لست أفهم كثيرًا في سانكتوم، لكن التوثيق الخاص بهم يقول بعد الترجمة: 

اقتباس

 

مصادقة تطبيق أحادي الصفحة (SPA) 
يوجد Sanctum أيضًا لتوفير طريقة بسيطة لمصادقة التطبيقات أحادية الصفحة  (SPAs) التي تحتاج إلى التواصل مع واجهة برمجة التطبيقات المدعومة بـ Laravel. قد تكون التطبيق الأحادي موجودة في نفس المستودع مثل تطبيق Laravel الخاص بك أو قد تكون مستودعًا منفصلاً تمامًا.

بالنسبة لهذه الميزة، لا يستخدم Sanctum الرموز المميزة من أي نوع. بدلاً من ذلك، يستخدم Sanctum خدمات مصادقة الجلسة المبنية على ملفات تعريف الارتباط من Laravel. يوفر هذا الأسلوب للمصادقة فوائد حماية CSRF، ومصادقة الجلسة، بالإضافة إلى الحماية من تسرب بيانات اعتماد المصادقة عبر XSS.

من أجل المصادقة، يجب أن يتشارك SPA وAPI في نفس نطاق (domain) المستوى الأعلى. ومع ذلك، يمكن وضعها في نطاقات فرعية مختلفة. بالإضافة إلى ذلك، يجب عليك التأكد من إرسال رأس Accept: application/json وإما رأس Referer أو Origin مع طلبك.

 

هذا يعني أن مقترحك خطأ، لا تقم ب:  
 

fetch('/api/user', {
  headers: {
    Authorization: 'Bearer YOUR_TOKEN'
  }
})

بل بشيء شبيه بـ :
 

fetch('/api/user', {
  credentials: 'include'
})

تحقق أكثر من التوثيق هنا: 
https://laravel.com/docs/13.x/sanctum

تم التعديل في بواسطة شادي جـ
تدقيق
  • 0
نشر
بتاريخ 7 ساعة قال شادي جـ:

لست أفهم كثيرًا في سانكتوم، لكن التوثيق الخاص بهم يقول بعد الترجمة: 

هذا يعني أن مقترحك خطأ، لا تقم ب:  
 

fetch('/api/user', {
  headers: {
    Authorization: 'Bearer YOUR_TOKEN'
  }
})

بل بشيء شبيه بـ :
 

fetch('/api/user', {
  credentials: 'include'
})

تحقق أكثر من التوثيق هنا: 
https://laravel.com/docs/13.x/sanctum

للاسف لا زالت المشكلة موجودة

  • 0
نشر (معدل)
بتاريخ 3 ساعة قال Zerious San:

للاسف لا زالت المشكلة موجودة

عليك أن تشارك تفاصيل أكثر، شارك الخطأ نفسه. وهيكلة تطبيقك. وهل  SPA وAPI في نفس نطاق (domain) المستوى الأعلى؟ قد تكون مشكلة CORS أو CSRF.
يجب أن يكون كلا من التطبيق أحادي الصفحة وواجهة برمجة التطبيقات على نفس المستوى النطاق: 

  • api.example.com
  • spa.example.com

هل تستخدم REACT في الواجهة الأمامية؟

التالي ليس مصادقة عبر َAPI Token ولكن SPA API:


لتسهيل الأمور بدل استخدم fetch العادية استعمل حزمة axios للجلب.

انشئ ملف اسمه api.js في الواجهة الأمامية فيه التالي:
 

import axios from "axios";

const api = axios.create({
  baseURL: "http://api.example.com",
  withCredentials: true,
  headers: {
    Accept: "application/json"
  }
});

export default api;

لاحظ أننا نستعمل axios هنا، احرص على تثبيته.
ثم في مكون تسجيل الدخول يجب أن تجلب CSRF Cookie أولًا :
 

const login = async () => {
// 1. جلب CSRF Cookie
await api.get("/sanctum/csrf-cookie");

// 2. تسجيل الدخول
await api.post("/login", {
email: email.value,
password: password.value
});

};

بالنسبة للواجهة الخلفية تأكد من ملف تكوين CORٍS  config/cors.php، يجب أن يكون شيء على شاكلة هذا:
 

return [
    'paths' => ['api/*', 'sanctum/csrf-cookie'],
    'allowed_origins' => ['http://spa.example.com'],
    'allowed_methods' => ['*'],
    'allowed_headers' => ['*'],
    'supports_credentials' => true,
];

الـ CORS هي اختصار لتشارك الموارد عبر الأصول، والأصل قد يكون اسم نطاق example.com أو برتوكول أو منفذ. إذا كان سانكتوم لا يسمح بالأصل الذي فيه تطبيق الواجهة الأمامية سيحدث عندك خطأ في المصادقة. لهذا يجب أن نضع اسم النطاق في allowed_origins (الأصول المسموح بها).

أيضا احرص على تكوين متغيرات البيئة .env كالتالي:

SESSION_DRIVER=cookie // مهم لتخزين بيانات الجلسة في ملفات تعريف الارتباط
SESSION_DOMAIN=.example.com // يسمح للجلسة في العمل في النطاقات الفرعية 

SANCTUM_STATEFUL_DOMAINS=spa.example.com // يُخبر لارفال أن نطاق تطبيق الواجهة الأمامية موثوق ويستخدم الجلسات

هذه الخطوة مهمة، من دونها قد تفشل المصادقة، لأن:
SESSION_DOMAIN=.example.com   
تسمح لمفات تعريف الارتباط  العمل في النطاقات الفرعية (sub-domains) مثل spa.exmple.com و api.exmple.com.

وأخيرًا  في app/Http/Kernel.php:

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

شرح:
 

\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class

 يجعل سانكتوم يعمل مع التطبيق أحادي الصفحة باستخدام جلسة session بدل token.

أتمنى أن يساعدك هذا على حل مشكلتك. لو استمرت المشكلة، شارك تفاصيل أكثر.  بالتوفيق!

تم التعديل في بواسطة شادي جـ
تدقيق
  • 1
نشر (معدل)

السابق لم يكن عبر API Token، إذا كنت تريد عبر API Token، فإنسي كل السابق، وتأكد فقط من مشاركة الموارد عبر الأصول CORS للنطاق الخاص بالواجهة الأمامية كما أوضحت سابقا.. لربما كان هذا خطأك منذ البداية. أيضا  لا تستخدم \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class لأن هذا للجلسات فقط وليس باستخدام توكن. واهمل أيضًا متغيرات البيئة في الرد السابق، لأنها خاصة كما ذكرنا بالجلسات. لم تزودني منذ البداية بتفاصيل كافية، لهذا تهت. 

أما بالنسبة للواجهة الأمامية عبر استخدام token فهي كالتالي:
 

1. تسجيل الدخول والحصول على Token

const response = await fetch("http://api.example.com/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
email: "test@example.com",
password: "password"
})
});
const data = await response.json();
const token = data.token;
// تخزين التوكن (مثلاً)
localStorage.setItem("token", token);


 

 2. استخدام التوكن في الطلبات

const token = localStorage.getItem("token");

const response = await fetch("http://api.example.com/api/user", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
}
});

const user = await response.json();
console.log(user);

 

تم التعديل في بواسطة شادي جـ
تدقيق
  • 0
نشر
بتاريخ 45 دقائق مضت قال شادي جـ:
localStorage.setItem("token", token);

عرفت الطريقة الصحيحة لاستخدام laravel sanctum.  حفظ api token بهذي الطريقة غير امن. شكرا على ردودك

  • 0
نشر (معدل)
بتاريخ 12 دقائق مضت قال Zerious San:

عرفت الطريقة الصحيحة لاستخدام laravel sanctum.  حفظ api token بهذي الطريقة غير امن. شكرا على ردودك

سعيد لأجلك! ومع ذلك، إن كنت قد توصّلت إلى الحل، فنحن ندعوك إلى مشاركته هنا. فهدف هذا الموقع هو تقديم يد العون لكل من يواجه المشكلة ذاتها، إذ يعمل على أرشفة المشكلات وحلولها في مكان واحد ليستفيد منه الجميع.

تم التعديل في بواسطة شادي جـ
تدقيق
  • 0
نشر
بتاريخ منذ ساعة مضت قال شادي جـ:

سعيد لأجلك! ومع ذلك، إن كنت قد توصّلت إلى الحل، فنحن ندعوك إلى مشاركته هنا. فهدف هذا الموقع هو تقديم يد العون لكل من يواجه المشكلة ذاتها، إذ يعمل على أرشفة المشكلات وحلولها في مكان واحد ليستفيد منه الجميع.

كيف ارفع مشاركتي؟ ام تقصد ارد عليك كيف عرفت الطريقة الصحيحة؟

  • 0
نشر
بتاريخ 1 دقيقة مضت قال Zerious San:

كيف ارفع مشاركتي؟ ام تقصد ارد عليك كيف عرفت الطريقة الصحيحة؟

نعم، رد هنا كما ترد عليّ الآن.

  • 1
نشر (معدل)
بتاريخ 7 ساعة قال شادي جـ:

نعم، رد هنا كما ترد عليّ الآن.

laravel sanctum  هو api بشكل كامل, فتحتاج token الذي تحصل بعد تسجيل الدخول الي هو 

Auth::user()->createToken("token-name")->plainTextToken;

و يكون المستخدم يعرف api token لانه لابد ان يستخدمه في bearer token في الخاص في header في javascript 

const name=await fetch("/addCompany",{
        method:"POST",
         headers: {
             'Accept': 'application/json',
             'Content-Type': 'application/json',
             "Authorization": `Bearer {token_value}`, // هنا لابد تكون token 
         }

لان middleware("auth:sanctum)  يعتمد على plainTextToken الذي نحصله بعد تسجيل المستخدم في التحقق من الصلاحية api و اذا بحث عن شروحات بتشوف الكثير يستخدم postman لانه يحاكي api بشكل كامل. و في التحقق من الصلاحية في خانة اسمها auth bearer token و هناك المستخدم يضع token خاص به للتحقق من الصلاحية. api route الي في ملف api.php يعتمد على bearer token في التحقق من الصلاحية.

 

اذا تريد تستخدم fetch api بدون bearer token استخدم الرابط الخاص الموجود web route الي في ملف web.php لان بيستخدم csrf token في التحقق من الصلاحية  و middleware("auth) يتحقق من تسجيل الدخول الخاص بالمستخدم الافضل استخدامه لزيادة الامان اذا كان api في مشروعك يعتمد على التحقق من تسجيل دخول. وهو لا يعتمد على bearer token و تقدر تزيد الامان له في controller الخاص مثل التحقق من الدخول auth:check() و التحقق من role اذا كان لديك هذا الشي في مشروعك.

و

csrf token يمكن وضعه في header او body 
 

header:

const name=await fetch("addCompany",{
        method:"POST",
         headers: {
             'Accept': 'application/json',
            'Content-Type': 'application/json',
             "X-CSRF-Token": document.querySelector('input[name=_token]').value

         },

body:

const name=await fetch("addCompany",{
        method:"POST",
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',

        },
        body: JSON.stringify({_token:document.querySelector('input[name=_token]').value})

 

تم التعديل في بواسطة Zerious San
  • 0
نشر

الأفضل لك هو SPA Authentication وCookies حيث لا تحتاج لـ Bearer Token، والمتصفح يتعامل مع كل شيء تلقائياً.

كود fetch سيكون كالتالي:

await fetch('http://your-backend.test/sanctum/csrf-cookie', {
    method: 'GET',
    credentials: 'include' 
});

const loginResponse = await fetch('http://your-backend.test/login', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    },
    credentials: 'include', 
    body: JSON.stringify({ email: 'user@test.com', password: 'password' })
});

const protectedResponse = await fetch('http://your-backend.test/api/user', {
    method: 'GET',
    credentials: 'include'
});
const user = await protectedResponse.json();

لاحظ  credentials: 'include' لارسال واستقبال الكوكيز، أي يتم إرساله تلقائيًا.

وفي ملف.env في لارافل يجب إعداده بشكل صحيح:

SESSION_DOMAIN=backend.test
SANCTUM_STATEFUL_DOMAINS=frontend.test

حيث يجب أن يكون الـ Front-end و Back-end على نفس الـ Top-Level Domain بمعنى api.site.com و www.site.com.

 

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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.

  • إعلانات

  • تابعنا على



×
×
  • أضف...