فهم Laravel Passport
يوفر Laravel Passport تنفيذاً كاملاً لخادم OAuth2 لتطبيق Laravel الخاص بك. إنه مثالي عندما تحتاج إلى دعم مصادقة OAuth من طرف ثالث، أو أنواع منح متعددة، أو عند بناء أنظمة مصادقة معقدة.
ما هو OAuth2؟
OAuth2 هو إطار عمل للتفويض يمكّن التطبيقات من الحصول على وصول محدود إلى حسابات المستخدمين على خدمة HTTP. المفاهيم الرئيسية:
- مالك المورد: المستخدم الذي يفوض الوصول إلى حسابه
- العميل: التطبيق الذي يطلب الوصول إلى حساب المستخدم
- خادم التفويض: يصدر رموز الوصول بعد المصادقة الناجحة
- خادم المورد: يستضيف موارد المستخدم المحمية
- رمز الوصول: بيانات اعتماد تُستخدم للوصول إلى الموارد المحمية
- رمز التحديث: يُستخدم للحصول على رموز وصول جديدة عند انتهاء صلاحيتها
ملاحظة: استخدم Passport عندما تحتاج إلى وظيفة OAuth2 كاملة. لحالات الاستخدام الأبسط، Sanctum أخف وأسهل في التنفيذ.
تثبيت Passport
قم بتثبيت Passport عبر Composer:
composer require laravel/passport
php artisan migrate
php artisan passport:install
ينشئ أمر passport:install مفاتيح التشفير ويولد عملاء OAuth2.
تكوين Passport
أضف سمة HasApiTokens إلى نموذج المستخدم الخاص بك:
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
// ... باقي النموذج
}
سجل مسارات Passport في AuthServiceProvider:
use Laravel\Passport\Passport;
public function boot(): void
{
Passport::tokensExpireIn(now()->addDays(15));
Passport::refreshTokensExpireIn(now()->addDays(30));
Passport::personalAccessTokensExpireIn(now()->addMonths(6));
}
قم بتعيين برنامج تشغيل حارس API إلى passport في config/auth.php:
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
أنواع منح OAuth2
يدعم Passport أنواع منح متعددة لحالات استخدام مختلفة:
1. منح كلمة المرور (اسم المستخدم وكلمة المرور)
للتطبيقات الطرف الأول حيث تثق بالعميل ببيانات اعتماد المستخدم:
// إنشاء عميل منح كلمة المرور
php artisan passport:client --password
// طلب رمز
POST /oauth/token
{
"grant_type": "password",
"client_id": "client-id",
"client_secret": "client-secret",
"username": "user@example.com",
"password": "password",
"scope": "*"
}
نفذ منح كلمة المرور في متحكمك:
use Illuminate\Support\Facades\Http;
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$response = Http::post(url('/oauth/token'), [
'grant_type' => 'password',
'client_id' => config('passport.password_client_id'),
'client_secret' => config('passport.password_client_secret'),
'username' => $request->email,
'password' => $request->password,
'scope' => '*',
]);
if ($response->failed()) {
return response()->json([
'success' => false,
'message' => 'بيانات اعتماد غير صالحة'
], 401);
}
return response()->json([
'success' => true,
'data' => $response->json()
]);
}
نصيحة: قم بتخزين معرف العميل والسر في ملف .env الخاص بك للأمان.
2. منح رمز التفويض
لتطبيقات الطرف الثالث التي تحتاج إلى تفويض المستخدم:
// إنشاء عميل رمز التفويض
php artisan passport:client
// الخطوة 1: إعادة توجيه المستخدم إلى عنوان URL للتفويض
GET /oauth/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&response_type=code&scope=*
// الخطوة 2: يوافق المستخدم، يستلم رمز التفويض
// الخطوة 3: تبادل الرمز برمز الوصول
POST /oauth/token
{
"grant_type": "authorization_code",
"client_id": "client-id",
"client_secret": "client-secret",
"redirect_uri": "https://your-app.com/callback",
"code": "authorization-code"
}
3. منح بيانات اعتماد العميل
للمصادقة من آلة إلى آلة بدون تدخل المستخدم:
// إنشاء عميل بيانات اعتماد العميل
php artisan passport:client --client
// طلب رمز
POST /oauth/token
{
"grant_type": "client_credentials",
"client_id": "client-id",
"client_secret": "client-secret",
"scope": "*"
}
4. رموز الوصول الشخصية
لرموز API التي يولدها المستخدم (مشابه لـ Sanctum):
$token = $user->createToken('اسم الرمز')->accessToken;
// مع النطاقات
$token = $user->createToken('اسم الرمز', ['post-read', 'post-write'])->accessToken;
حماية المسارات باستخدام Passport
استخدم وسيط auth:api:
// routes/api.php
Route::middleware('auth:api')->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::apiResource('posts', PostController::class);
});
نطاقات الرموز
حدد النطاقات في AuthServiceProvider:
use Laravel\Passport\Passport;
public function boot(): void
{
Passport::tokensCan([
'post-read' => 'قراءة المنشورات',
'post-write' => 'إنشاء وتعديل المنشورات',
'post-delete' => 'حذف المنشورات',
'user-read' => 'قراءة ملف تعريف المستخدم',
'user-write' => 'تحديث ملف تعريف المستخدم',
]);
Passport::setDefaultScope([
'post-read',
'user-read',
]);
}
تحقق من النطاقات في مساراتك:
// اطلب نطاق محدد
Route::middleware(['auth:api', 'scope:post-write'])
->post('/posts', [PostController::class, 'store']);
// اطلب أي من النطاقات
Route::middleware(['auth:api', 'scopes:post-read,post-write'])
->get('/posts', [PostController::class, 'index']);
// تحقق من النطاقات في المتحكم
public function store(Request $request)
{
if (!$request->user()->tokenCan('post-write')) {
return response()->json([
'error' => 'أذونات غير كافية'
], 403);
}
// إنشاء منشور...
}
تحديث الرموز
اطلب رموز وصول جديدة باستخدام رموز التحديث:
POST /oauth/token
{
"grant_type": "refresh_token",
"refresh_token": "the-refresh-token",
"client_id": "client-id",
"client_secret": "client-secret",
"scope": "*"
}
تعامل مع تحديث الرمز في تطبيقك:
public function refresh(Request $request)
{
$request->validate([
'refresh_token' => 'required',
]);
$response = Http::post(url('/oauth/token'), [
'grant_type' => 'refresh_token',
'refresh_token' => $request->refresh_token,
'client_id' => config('passport.password_client_id'),
'client_secret' => config('passport.password_client_secret'),
'scope' => '*',
]);
return response()->json($response->json());
}
إلغاء الرموز
اسمح للمستخدمين بإلغاء رموز الوصول:
public function logout(Request $request)
{
$request->user()->token()->revoke();
return response()->json([
'success' => true,
'message' => 'تم تسجيل الخروج بنجاح'
]);
}
// إلغاء جميع الرموز للمستخدم
$user->tokens->each(function ($token) {
$token->revoke();
});
مقارنة Passport و Sanctum
| الميزة |
Sanctum |
Passport |
| التعقيد |
بسيط |
معقد |
| دعم OAuth2 |
لا |
نعم |
| مصادقة SPA |
نعم (ملف تعريف ارتباط) |
نعم (رمز) |
| تطبيقات الجوال |
نعم |
نعم |
| تطبيقات الطرف الثالث |
لا |
نعم |
| تحديث الرمز |
لا |
نعم |
| النطاقات |
أساسي |
متقدم |
تمرين:
- قم بتثبيت وتكوين Passport في تطبيقك
- أنشئ عميل منح كلمة المرور ونفذ نقطة نهاية تسجيل الدخول
- حدد نطاقات مخصصة للمنشورات (قراءة، كتابة، حذف) والمستخدمين (قراءة، كتابة)
- نفذ نقطة نهاية تحديث الرمز
- أنشئ وسيط يتحقق من نطاقات محددة قبل السماح بالإجراءات
- اختبر تنفيذك باستخدام Postman أو عميل REST
أفضل ممارسات الأمان
- استخدم HTTPS: استخدم دائماً HTTPS لحماية الرموز أثناء النقل
- أسرار العميل الآمنة: قم بتخزين أسرار العميل بشكل آمن، لا تعرضها أبداً في كود الواجهة الأمامية
- عمر رمز قصير: استخدم رموز وصول قصيرة الأجل (15-60 دقيقة) ورموز تحديث أطول
- تدوير الأسرار: قم بتدوير أسرار العميل بشكل دوري للأمان
- حد النطاقات: امنح الحد الأدنى من الأذونات الضرورية للرموز
- تحديد المعدل: نفذ تحديد المعدل على نقاط نهاية OAuth
- سجلات التدقيق: سجل إصدار الرموز واستخدامها للتدقيق الأمني
- الإلغاء: نفذ إلغاء الرمز للرموز المعرضة للخطر
الخلاصة
يوفر Laravel Passport تنفيذاً كاملاً لخادم OAuth2 مع أنواع منح متعددة وتحديث الرموز وإدارة النطاق المتقدمة. على الرغم من كونه أكثر تعقيداً من Sanctum، إلا أنه ضروري للتطبيقات التي تحتاج إلى دعم مصادقة OAuth من طرف ثالث أو تتطلب ميزات تفويض على مستوى المؤسسة. اختر Passport عند بناء منصات تسمح بتكاملات الطرف الثالث أو تحتاج إلى امتثال OAuth2.