مقدمة: لماذا نحتاج إلى OAuth 2.0 و JWT في PHP
تطبيقات الويب الحديثة نادراً ما تعمل بشكل منعزل. يتوقع المستخدمون تسجيل دخول موحد عبر Google أو Facebook أو GitHub، ويتوقع المطورون تبادلاً آمناً للبيانات بين الخدمات المصغرة. بروتوكولان رئيسيان — OAuth 2.0 (تفويض الوصول) و JWT (تنسيق رمز مضغوط) — أصبحا المعيار الفعلي. في هذه المقالة، سنشرح كيفية تنفيذ OAuth 2.0 و JWT للتحقق من الهوية في PHP من الصفر، باستخدام إمكانيات اللغة المضمنة فقط والمكتبات الشائعة. ستحصل على أمثلة جاهزة للكود للتكامل مع المزودين الخارجيين وإنشاء نظام المصادقة الخاص بك.
1. أساسيات OAuth 2.0: التدفقات والأدوار
OAuth 2.0 هو بروتوكول تفويض يسمح للتطبيقات الخارجية بالحصول على وصول محدود إلى موارد المستخدم دون نقل كلمة المرور. يشارك فيه أربعة أدوار:
- Resource Owner — المستخدم، مالك البيانات.
- Client — تطبيق PHP الخاص بك، الذي يطلب الوصول.
- Authorization Server — الخادم الذي يصدر الرموز (مثل Google).
- Resource Server — API الذي يوفر البيانات بناءً على الرمز.
التدفق الأكثر شيوعاً لتطبيقات الويب هو Authorization Code Grant. إنه آمن، حيث يتم نقل الرمز عبر الجزء الخادم، وليس عبر المتصفح. دعنا ننظر في التنفيذ في PHP.
1.1. تسجيل التطبيق والحصول على Client ID/Secret
قبل كتابة الكود، قم بتسجيل التطبيق لدى المزود (على سبيل المثال، في Google Cloud Console). ستحصل على client_id و client_secret، وستقوم أيضاً بتكوين redirect URI (على سبيل المثال، https://موقعك.كوم/callback.php).
1.2. تنفيذ تدفق Authorization Code في PHP
سنقوم بإنشاء ملفين: login.php (إعادة التوجيه إلى خادم التفويض) و callback.php (معالجة الرد).
ملف login.php
<?phpsession_start();
$client_id = 'CLIENT_ID_الخاص_بك';$redirect_uri = 'https://موقعك.كوم/callback.php';$state = bin2hex(random_bytes(16)); // حماية من CSRF$_SESSION['oauth_state'] = $state;
$params = http_build_query([ 'client_id' => $client_id, 'redirect_uri' => $redirect_uri, 'response_type' => 'code', 'scope' => 'openid email profile', 'state' => $state,]);
header('Location: https://accounts.google.com/o/oauth2/v2/auth?' . $params);exit;?>ملف callback.php
<?phpsession_start();
// التحقق من state (CSRF)if ($_GET['state'] !== $_SESSION['oauth_state']) { die('خطأ: state غير صحيح');}
$client_id = 'CLIENT_ID_الخاص_بك';$client_secret = 'CLIENT_SECRET_الخاص_بك';$redirect_uri = 'https://موقعك.كوم/callback.php';
// استبدال الكود برمز$ch = curl_init('https://oauth2.googleapis.com/token');curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'code' => $_GET['code'], 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'grant_type' => 'authorization_code',]));curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$response = curl_exec($ch);curl_close($ch);
$data = json_decode($response, true);$access_token = $data['access_token'] ?? null;
// الحصول على ملف تعريف المستخدم$ch = curl_init('https://www.googleapis.com/oauth2/v2/userinfo');curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $access_token]);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$userInfo = json_decode(curl_exec($ch), true);curl_close($ch);
echo 'مرحباً، ' . htmlspecialchars($userInfo['email']);?>هام: تحقق دائماً من المعامل state. إنه يحمي من تزوير الطلب (CSRF).