الاستثياق باستخدام واجهة API خارجية (API Authentication) في Laravel

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

مقدمة

يعمل Laravel بالفعل على تسهيل إجراء الاستيثاق عبر نماذج تسجيل الدخول التقليدية، ولكن ماذا عن الواجهات البرمجيّة (APIs)؟ تستخدم الواجهة البرمجيّة عادةً رموز (Tokens) لاستيثاق المستخدمين ولا تحتفظ بحالة الجلسة بين الطلبات. يجعل Laravel استيثاق الواجهة البرمجيّة سهلًا جدًا باستخدام واجهة API خارجية.

(Laravel Passport) ، والتي توفر تطبيق خادم OAuth2 الكامل لتطبيق Laravel في غضون دقائق. الجوازات مبنية على خادم OAuth2 League المُصان بواسطة أندي ميلينغتون و سيمون هامب.

يفترض هذا المستند أنك معتاد بالفعل على اصطلاحات OAuth2. إذا كنت لا تعرف شيئًا عن OAuth2، ففكر في التعرف على المصطلحات العامة وخصائص OAuth2 قبل المتابعة.

التثبيت

للبدء، ثبّت الواجهة البرمجية Passport عبر Composer:

composer require laravel/passport

يسجّل موفر خدمة جواز السفر (Passport) مجلد تهجير قاعدة البيانات (database migration) الخاص به مع الإطار، لذلك يجب تهجير قاعدة البيانات الخاصة بك بعد تسجيل الموفر. سوف تُنشئ عمليات تهجير جواز السفر الجداول التي يحتاجها تطبيقك لتخزين العملاء والوصول إلى الرموز (Tokens):

php artisan migrate

إذا كنت لا تريد استخدام عمليات التهجير الافتراضية الخاصة بخدمة Passport، استدع التابع Passport::ignoreMigrations في التابع register الخاص بمزود الخدمة AppServiceProvider. يجوز لك تصدير عمليات التهجير الافتراضية باستخدام الأمر :

php artisan vendor:publish --tag=passport-migrations

بعد ذلك، نفذ الأمر passport:install. سيُنشِئ هذا الأمر مفاتيح التشفير اللازمة لإنشاء رموز (token) آمنة. بالإضافة إلى ذلك، سيعمل الأمر على إنشاء عملاء "وصول شخصي" (personal access) و "منحة كلمة المرور" (password grant) التي ستُستخدم لتوليد رموز الوصول (access tokens):

php artisan passport:install

بعد تنفيذ هذا الأمر، أضف السمة Laravel\Passport\HasApiTokens إلى نموذج App\User. ستوفر هذه السمة عددًا قليلًا من التوابع المساعدة إلى نموذجك الذي يسمح لك بتفقد الرموز والنطاقات (scopes) للمستخدم المصادق عليه:

namespace App;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable

{
   use HasApiTokens, Notifiable;
}

بعد ذلك، استدع التابع Passport::routes داخل التابع boot الموجود في AuthServiceProvider الخاص بك. يُسجِّل هذا التابع المسارات اللازمة لإصدار رموز الدخول ورفض رموز الوصول والعملاء ورموز الوصول الشخصية:

namespace App\Providers;

use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider

{
   /**
    * التعيينات السياسية للتطبيق.
    *
    * @var array
    */

   protected $policies = [
       'App\Model' => 'App\Policies\ModelPolicy',
   ];

   /**
    * تسجيل أي خدمة استيثاق / ترخيص
    *
    * @return void
    */

   public function boot()

   {
       $this->registerPolicies();
       Passport::routes();
   }
}

وأخيرًا، في ملف الضبط config/auth.php، يجب عليك تعيين driver الخاص بحارس الاستيثاق api على passport. مما يطلب من تطبيقك أن يستخدم TokenGuard الذي يتبع إلى Passport عند الاستيثاق من طلبيات الاستيثاق القادمة من واجهة API:

'guards' => [

   'web' => [

      'driver' => 'session',
      'provider' => 'users',
   ],

   'api' => [

       'driver' => 'passport',
       'provider' => 'users',
   ],
],

بداية سريعة للواجهة الأمامية

لاستخدام مكونات Passport Vue، استخدم إطار عمل Vue. تستخدم هذه المكونات أيضًا إطار عمل Bootstrap. ومع ذلك، حتى إذا كنت لا تستخدم هذه الأدوات، فإن المكونات تعدّ مرجعًا قيمًا يفيدك عند برمجة الواجهة الخاصة بك.

يأتي Passport مع JSON API التي يمكنك استخدامها للسماح للمستخدمين بإنشاء عملاء ورموز وصول شخصية. ومع ذلك، يمكن أن يستغرق الأمر وقتًا طويلًا لبرمجة الواجهة الأمامية للتفاعل مع واجهات البرمجية هذه. لذلك، يشمل Passport أيضًا على مكونات Vue جاهزة التي قد تستخدمها كمثال للتنفيذ أو كنقطة انطلاق لبرمجة مكونات خاصة بك.

لنشر مكونات Passport Vue، استخدم الأمر  vendor:publish :

php artisan vendor:publish --tag=passport-components

تُوضع المكونات المنشورة في المجلد resources/assets/js/components. بمجرد نشر المكونات، يجب عليك تسجيلهم في ملف resources/assets/js/app.js :

Vue.component(

   'passport-clients',
   require('./components/passport/Clients.vue')

);

Vue.component(

   'passport-authorized-clients',
   require('./components/passport/AuthorizedClients.vue')

);

Vue.component(

   'passport-personal-access-tokens',
   require('./components/passport/PersonalAccessTokens.vue')

);

بعد تسجيل المكونات، تأكد من تشغيل الأمر npm run dev لإعادة ترجمة أصولك. بمجرد إعادة ترجمة الأصول، يمكنك وضع المكونات في أحد نماذج تطبيقك للبدء في إنشاء عملاء ورموز وصول شخصية :

<passport-clients></passport-clients>
<passport-authorized-clients></passport-authorized-clients>
<passport-personal-access-tokens></passport-personal-access-tokens>

نشر Passport

عند نشر Passport على خوادم الإنتاج لأول مرة، ستحتاج على الأرجح إلى تنفيذ الأمر passport:keys. ينشئ هذا الأمر مفاتيح التشفير التي يحتاجها Passport لإنشاء رمز وصول. لا يُحتفظ بالمفاتيح التي أُنشِئت عادة في مصادر التحكم:

php artisan passport:keys

الضبط

دورة حياة الرموز

يصدر Passport افتراضيًا رموز وصول طويلة الأمد تنتهي صلاحيتها بعد مرور عام. إذا كنت ترغب في ضبط مدة صلاحية الرموز لتكون أطول أو أقصر، يمكنك استخدام التابعين tokensExpireIn و refreshTokensExpireIn. يجب استدعاء هذه التوابع من التابع boot الخاص بالمزود AuthServiceProvider:

/**
* تسجيل أي خدمات الاستيثاق/ الترخيص
*
* @return void
*/

public function boot()

{

   $this->registerPolicies();
   Passport::routes();
   Passport::tokensExpireIn(now()->addDays(15));
   Passport::refreshTokensExpireIn(now()->addDays(30));

}

إصدار رموز الوصول

يعرف معظم المطورين OAuth من خلال استعماله مع رموز الترخيص (authorization codes). عند استخدام رموز الترخيص، سيعيد تطبيق الزبون توجيه المستخدم إلى خادمك حيث سيوافق أو يرفض طلب إصدار رمز دخول مميز إلى الزبون.

إدارة العملاء

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

الأمر passport:client

أبسط طريقة لإنشاء عميل هي استخدام أمر passport:client Artisan. يمكن استخدام هذا الأمر لإنشاء عملاء خاصين بك لاختبار وظائف OAuth2. عند تنفيذ أمر client، يطالبك Passport بمزيد من المعلومات حول العميل و يزودك بمعرّف عميل ID و كلمة سرية:

php artisan passport:client

واجهة ‎(API) JSON

نظرًا لأن مستخدمي تطبيقك لن يتمكنوا من استخدام أمر client، يوفر Passport واجهة JSON التي قد تستخدمها لإنشاء عملاء. هذا يوفر عليك عناء الاضطرار إلى برمجة وحدات التحكم (Controllers) يدويًا لإنشاء، أو تحديث، أو حذف العملاء.

ومع ذلك، ستحتاج إلى إقران واجهة JSON التي تتبع إلى Passport مع الواجهة الأمامية الخاصة بك لتوفير لوحة تحكم للمستخدمين لإدارة عملائهم. في ما يلي، سنراجع جميع نقاط نهاية الواجهة API لإدارة العملاء. للسهولة، سنستخدم Axios لإرسال طلبيات HTTP إلى نقاط النهاية.

ملاحظة: إذا كنت لا ترغب في برمجة واجهة إدارة العميل بالكامل بنفسك، فيمكنك استخدام بدء سريع للواجهة الأمامية للحصول على واجهة أمامية كاملة في غضون دقائق.

GET /oauth/clients

يقوم هذا المسار بإرجاع كافة العملاء للمستخدم المصادق عليه. هذا مفيد بشكل أساسي لإدراج كافة عملاء المستخدم بحيث يمكنه تعديلها أو حذفها:

axios.get('/oauth/clients')

   .then(response => {
       console.log(response.data);

   });
POST /oauth/clients

يستخدم هذا المسار لإنشاء عملاء جدد. ويتطلب معلومتين: اسم العميل (name) وعنوان URL لإعادة التوجيه (redirect). عنوان URL هو المكان الذي سيعاد توجيه المستخدم إليه بعد الموافقة على طلب الترخيص أو رفضه.

عند إنشاء عميل، يتم إصدار معرف العميل وسر العميل. يتم استخدام هذه القيم عند طلب رمز الوصول من تطبيقك. يُعيد مسار إنشاء العميل نسخة العميل الجديد:

onst data = {
   name: 'Client Name',
   redirect: 'http://example.com/callback'
};

axios.post('/oauth/clients', data)
   .then(response => {
       console.log(response.data);
   })

   .catch (response => {

      // عدّد الأخطاء عند الإجابة ...
   });
{PUT /oauth/clients/{client-id

يستخدم هذا المسار لتحديث العملاء. يتطلب معلومتين: اسم العميل وعنوان URL لإعادة التوجيه. عنوان URL هو المكان الذي سيعاد توجيه المستخدم إليه بعد الموافقة على طلب الترخيص أو رفضه. سيعيد المسار نسخة العميل المُحدّثة:

const data = {
   name: 'New Client Name',
   redirect: 'http://example.com/callback'

};

axios.put('/oauth/clients/' + clientId, data)
   .then(response => {
       console.log(response.data);
   })

   .catch (response => {
      // List errors on response...
   });
{DELETE /oauth/clients/{client-id

يستخدم هذا المسار لحذف العملاء:

axios.delete('/oauth/clients/' + clientId)
   .then(response => {
      //
   });

طلب الرموز

إعادة التوجيه للحصول على الترخيص

بمجرد إنشاء عميل، يمكن للمطورين استخدام مُعرّف العميل وسرّه لطلب رمز الترخيص ورمز الوصول من تطبيقك. أولاً، يجب أن يجري التطبيق المُستهلِك طلب إعادة توجيه إلى مسار oauth/authorize الخاص بتطبيقك كما يلي:

Route::get('/redirect', function () {

   $query = http_build_query([

       'client_id' => 'client-id',
       'redirect_uri' => 'http://example.com/callback',
       'response_type' => 'code',
       'scope' => '',
   ]);

   return redirect('http://your-app.com/oauth/authorize?'.$query);
});

ملاحظة: تذكر، المسار ‎/oauth/authorize معرف مسبقًا بواسطة التابع Passport::routes. لست بحاجة إلى تحديد هذا المسار يدويًا.

الموافقة على الطلب

عند تلقي طلبات الترخيص، سيعرض Passport تلقائيًا قالبًا على المستخدم يسمح له بالموافقة على أي طلب للترخيص أو رفضه. إذا وافق على الطلب، فسيعاد التوجيه إلى redirect_uri الذي حُدّد من خلال التطبيق المُستهلِك. يجب أن يتطابق redirect_uri مع عنوان URL redirect الذي حُدّد عند إنشاء العميل.

إذا كنت ترغب في تخصيص شاشة الموافقة على الترخيص، فيمكنك نشر واجهات Passport باستخدام أمر vendor:publish Artisan. ستوضع الواجهة المنشورة في resources/views/vendor/passport :

php artisan vendor:publish --tag=passport-views

تحويل رموز الترخيص إلى رموز وصول

إذا وافق المستخدم على طلب الترخيص، فسيعاد توجيهه مرة أخرى إلى التطبيق المُستهلِك. يجب على المُستهلِك بعد ذلك إصدار طلب POST إلى تطبيقك لطلب رمز وصول. يجب أن يتضمن الطلب رمز الترخيص الذي أُصدر من تطبيقك عندما وافق المستخدم على طلب الترخيص. في هذا المثال، سنستخدم مكتبة Guzzle HTTP لإجراء طلب POST :

Route::get('/callback', function (Request $request) {

   $http = new GuzzleHttp\Client;
   $response = $http->post('http://your-app.com/oauth/token', [

       'form_params' => [

           'grant_type' => 'authorization_code',
           'client_id' => 'client-id',
           'client_secret' => 'client-secret',
           'redirect_uri' => 'http://example.com/callback',
           'code' => $request->code,

       ],
   ]);
   return json_decode((string) $response->getBody(), true);

});

يعيد المسار ‎/oauth/token رد JSON يحتوي على رموز الوصول access_token، refresh_token، وخاصية expires_in. تحتوي خاصية expires_in على وقت نهاية صلاحية رمز الوصول.

ملاحظة: كما في مسار oauth/authorize/، يُعرّف المسار ‎/oauth/token من خلال التابع Passport::routes. لا حاجة لتحديد هذا المسار يدويًا.

تحديث الرموز

إذا كان تطبيقك يصدر رموز وصول قصيرة العمر، سيحتاج المستخدمون إلى تحديث رموز الوصول الخاصة بهم عبر رمز التحديث الذي وُفّر عند إصدار رمز الوصول. في هذا المثال، سوف نستخدم مكتبة Guzzle HTTP لتحديث الرمز:

$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [

   'form_params' => [

       'grant_type' => 'refresh_token',
       'refresh_token' => 'the-refresh-token',
       'client_id' => 'client-id',
       'client_secret' => 'client-secret',
       'scope' => '',

   ],
]);

return json_decode((string) $response->getBody(), true);

سيعرض هذا المسار ‎/oauth/token رد JSON التي تحتوي على سمات access_token، و refresh_tokenو expires_in. تحتوي السمة expires_in على عدد الثواني حتى تنتهي صلاحية رمز الوصول.

رموز منحة كلمة المرور Password Grant Tokens

تسمح منحة كلمة مرور OAuth2 للطرف الأول لعملائك، مثل تطبيق الجوال، بالحصول على رمز وصول باستخدام عنوان البريد الإلكتروني أو اسم المستخدم وكلمة المرور. يتيح لك هذا إصدار رموز الدخول بشكل آمن إلى عملاء الطرف الأول دون مطالبة المستخدمين بالانتقال عبر رمز إعادة توجيه الترخيص OAuth2 بالكامل.

إنشاء عميل منحة كلمة المرور

قبل أن يتمكن تطبيقك من إصدار رموز عبر منحة كلمة المرور، تحتاج إلى إنشاء عميل لمنح كلمة المرور. يمكنك القيام بذلك باستخدام الأمر passport:client مع الخيار ‎--password. إذا كنت قد نفّذت الأمر passport:install، فلن تحتاج إلى تنفيذ هذا الأمر:

php artisan passport:client --password

طلب الرموز

بمجرد إنشاء عميل منحة كلمة المرور، يمكنك طلب رمز وصول عن طريق إصدار طلب POST إلى المسار ‎/oauth/token باستخدام عنوان البريد الإلكتروني وكلمة المرور الخاصين بالمستخدم. تذكر، تم تسجيل هذا المسار بواسطة التابع Passport::routes لذلك لا حاجة لتعريفه يدويًّا. إذا كان الطلب ناجحًا، سوف تتلقى access_token و refresh_token في رد JSON من الخادم :

$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [

   'form_params' => [

       'grant_type' => 'password',
       'client_id' => 'client-id',
       'client_secret' => 'client-secret',
       'username' => 'taylor@laravel.com',
       'password' => 'my-password',
       'scope' => '',

   ],
]);

return json_decode((string) $response->getBody(), true);

ملاحظة: تذكر أن عمر رموز الوصول طويل افتراضيًا. ومع ذلك، أنت حر في ضبط الحد الأقصى لعمر رموز الوصول إذا لزم الأمر.

طلب جميع النطاقات

عند استخدام منحة كلمة المرور، قد ترغب في ترخيص الرمز لجميع النطاقات التي يدعمها تطبيقك. يمكنك القيام بذلك عن طريق طلب النطاق *. إذا طلبت النطاق *، فسيرجع التابع can على نسخة الرمز true القيمة دومًا. قد يُعيّن هذا النطاق فقط لرمز أُصدر باستخدام منح كلمة المرور:

$response = $http->post('http://your-app.com/oauth/token', [

   'form_params' => [

       'grant_type' => 'password',
       'client_id' => 'client-id',
       'client_secret' => 'client-secret',
       'username' => 'taylor@laravel.com',
       'password' => 'my-password',
       'scope' => '*',

   ],
]);

منح رموز ضمنية

المنحة الضمنية مشابهة لمنح رمز الترخيص، ومع ذلك، يُعاد الرمز إلى العميل دون تبادل رمز الترخيص. تُستخدم هذه المنحة بشكلٍ شائع لتطبيقات JavaScript أو تطبيقات الجوّال حيث لا يمكن تخزين بيانات اعتماد العميل بأمان. لتمكين المنحة، استدعِ التابع enableImplicitGrant في AuthServiceProvider الخاص بك:

/**

* تسجيل أي خدمة استيثاق / ترخيص
*
* @return void

*/

public function boot()

{
   $this->registerPolicies();
   Passport::routes();
   Passport::enableImplicitGrant();
}

بمجرد تمكين المنحة، قد يستخدم المطورون مُعرّف العميل الخاص بهم لطلب رمز وصول من تطبيقك. يجب أن يقوم التطبيق المُستهلِك بإجراء طلب إعادة توجيه إلى مسار ‎/oauth/authorize الخاص بتطبيقك كما يلي:

Route::get('/redirect', function () {

   $query = http_build_query([

       'client_id' => 'client-id',
       'redirect_uri' => 'http://example.com/callback',
       'response_type' => 'token',
       'scope' => '',
   ]);

   return redirect('http://your-app.com/oauth/authorize?'.$query);
});

ملاحظة: تذكر أن المسار ‎/oauth/authorize مُعرّف مسبقًا بواسطة التابع Passport::route. لست بحاجة إلى تعريف هذا المسار يدويًا.

رموز منح معلومات اعتماد العميل

منحة بيانات اعتماد العميل مناسبة لاستيثاق جهاز لجهاز. على سبيل المثال، قد تستخدم هذه المنحة في مهمة مجدولة تُنفِّذ مهام الصيانة على واجهة API. لاستخدام هذه الطريقة، تحتاج أولًا إلى إضافة وسيط جديد إلى ‎$routeMiddleware في app/Http/Kernel.php :

use Laravel\Passport\Http\Middleware\CheckClientCredentials;

protected $routeMiddleware = [
  'client' => CheckClientCredentials::class,

];

ثم اربط هذا الوسيط بمسار :

Route::get('/user', function(Request $request) {
   ...

})->middleware('client');

للحصول على رمز مميّز، قدّم طلبًا لنقطة النهاية oauth/token:

$guzzle = new GuzzleHttp\Client;
$response = $guzzle->post('http://your-app.com/oauth/token', [

   'form_params' => [

       'grant_type' => 'client_credentials',
       'client_id' => 'client-id',
       'client_secret' => 'client-secret',
       'scope' => 'your-scope',

   ],
]);

return json_decode((string) $response->getBody(), true)['access_token'];

رموز الوصول الشخصية

في بعض الأحيان، قد يرغب المستخدمون في إصدار رموز الوصول لأنفسهم دون المرور بإعادة التوجيه العادي لرمز الترخيص. يمكن للسماح للمستخدمين بإصدار الرموز المميزة لأنفسهم عبر واجهة المستخدم الخاصة بتطبيقك أن يكون مفيدًا في السماح للمستخدمين بتجربة واجهة API الخاصة بك أو قد يكون بمثابة أسلوب أبسط لإصدار رموز الوصول بشكل عام.

تحذير: رموز الوصول الشخصية دائما طويلة العمر. لا يُعدّل عمرها عند استخدام التابعين tokensExpireIn أو refreshTokensExpireIn.

إنشاء عميل الوصول الشخصي

قبل أن يتمكن تطبيقك من إصدار رموز وصول شخصية، تحتاج إلى إنشاء عميل وصول شخصي. يمكنك ذلك باستخدام الأمر passport:client مع الخيار ‎--personal. إذا كنت قد نفّذت بالفعل أمر passport:install، فلن تحتاج إلى تنفيذ هذا الأمر:

php artisan passport:client --personal

إدارة رموز الوصول الشخصية

بمجرد إنشاء عميل وصول شخصي، يجوز لك إصدار الرموز المميزة لمُستخدِم مُعين باستخدام التابع createToken على نسخة نموذج User. يقبل التابع createToken اسم الرمز المميز كوسيط أول له (argument) ومصفوفة اختيارية من النطاقات كوسيط ثان له:

$user = App\User::find(1);

// إنشاء رمز مميز بدون نطاقات ...
$token = $user->createToken('Token Name')->accessToken;

// إنشاء رمز مميز بالنطاقات ...
$token = $user->createToken('My Token', ['place-orders'])->accessToken;

واجهة API JSON

يتضمن Passport أيضًا واجهة API JSON لإدارة رموز الوصول الشخصية. يمكنك إقران ذلك مع الواجهة الأمامية الخاصة بك لتزويد المستخدمين بلوحة تحكم لإدارة رموز الوصول الشخصية. فيما يلي، سنراجع جميع نقاط نهاية الواجهة API لإدارة رموز الوصول الشخصية. للسهولة، سنستخدم Axios لإنشاء طلبيات HTTP إلى نقاط النهاية.

ملاحظة: إذا لم ترغب في برمجة واجهة رموز الوصول الشخصية بنفسك، فيمكنك استخدام بدء سريع للواجهة الأمامية للحصول على واجهة أمامية كاملة في غضون دقائق.

GET /oauth/scopes

يعيد هذا المسار جميع النطاقات المعرفة من أجل التطبيق الخاص بك. يمكنك استخدام هذا المسار لسرد النطاقات التي يمكن للمستخدم تعيينها إلى رمز وصول شخصي:

axios.get('/oauth/scopes')
   .then(response => {
       console.log(response.data);

   });
GET /oauth/personal-access-tokens

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

axios.get('/oauth/personal-access-tokens')
   .then(response => {
       console.log(response.data);

   });
POST /oauth/personal-access-tokens

ينشئ هذا المسار رموز وصول شخصية جديدة. يتطلب ذلك وجود معلومتين: اسم الرمز المميز و النطاقات (scopes) التي يجب تعيينها إلى الرمز المميز :

const data = {
  name: 'Token Name',
   scopes: []

};

axios.post('/oauth/personal-access-tokens', data)
   .then(response => {
       console.log(response.data.accessToken);
   })

   .catch (response => {
      / /عدّد الأخطاء عند الإجابة...
   });

DELETE /oauth/personal-access-tokens/{token-id}‎

يُستخدم هذا المسار لحذف رموز الوصول الشخصية:

axios.delete('/oauth/personal-access-tokens/' + tokenId);

حماية المسارات

عن طريق برمجيّة وسيطة

يتضمن Passport حارس استيثاق يتحقق من رموز الوصول الخاصة بالطلبات الواردة. بمجرد ضبطك للحارس api لاستخدام مُشغّل passport، تحتاج فقط إلى تحديد البرمجيّة الوسيطة auth:api على أي مسار يتطلب رمز وصول صالح:

oute::get('/user', function () {
 //

})->middleware('auth:api');

تمرير رموز الوصول

عند استدعاء المسارات المحمية بواسطة Passport، يجب على مستعملي واجهة API الخاصة بتطبيقاتك تحديد رموز الوصول الخاص بهم كرمز Bearer في عنوان Authorization الخاص بطلبهم. على سبيل المثال، عند استخدام مكتبة Guzzle HTTP:

$response = $client->request('GET', '/api/user', [

   'headers' => [
       'Accept' => 'application/json',
       'Authorization' => 'Bearer '.$accessToken,
   ],
]);

نطاقات الرمز

تعريف النطاقات

تسمح النطاقات لزبائن واجهة API الخاصة بك بطلب مجموعة محددة من الرُخص عند طلب ترخيص للوصول إلى الحساب. على سبيل المثال، إذا كنت تنشئ تطبيقًا للتجارة الإلكترونية، فلن يحتاج جميع مستخدمي واجهة API إلى القدرة على تقديم طلبات. بدلًا من ذلك، يمكنك أن تسمح للمستخدمين بطلب الترخيص للوصول فقط إلى حالة شحن الطلبات. بعبارة أخرى، تتيح النطاقات لمستخدمي تطبيقك تحديد الأعمال التي يمكن أن يقدّمها تطبيق تابع لجهة خارجية نيابةً عنهم.

يمكنك تعريف نطاقات واجهة API الخاصة بك باستخدام التابع Passport::tokensCan في التابع boot لمزود الخدمة AuthServiceProvider الخاص بك. يقبل التابع tokensCan مصفوفة من أسماء النطاق وأوصاف النطاق. قد يكون وصف النطاق هو أي شيء تريده ويتم عرضه للمستخدمين على شاشة اعتماد الترخيص:

use Laravel\Passport\Passport;

Passport::tokensCan([

   'place-orders' => 'Place orders',
   'check-status' => 'Check order status',

]);

تعيين النطاقات للرموز

عند طلب رموز الترخيص

عند طلب رمز الوصول باستخدام منحة رمز الترخيص، يجب على المستهلكين تحديد نطاقاتهم المرغوبة كمعامل لاستعلام النطاق. يجب أن يكون معامل النطاق قائمة من النطاقات مفصولة بفراغات:

Route::get('/redirect', function () {

   $query = http_build_query([

       'client_id' => 'client-id',
       'redirect_uri' => 'http://example.com/callback',
       'response_type' => 'code',
       'scope' => 'place-orders check-status',
   ]);

   return redirect('http://your-app.com/oauth/authorize?'.$query);
});

عند إصدار رموز الوصول الشخصية

إذا كنت تصدر رموز وصول شخصية باستخدام التابع createToken الخاص بنموذج User، فيمكنك تمرير مصفوفة من النطاقات المطلوبة كوسيط ثان إلى الطريقة :

$token = $user->createToken('My Token', ['place-orders'])->accessToken;

فحص النطاقات

يتضمن Passport برمجيّتين وسيطتين يمكن استخدامهما للتحقق من أن طلبًا واردًا مصادق عليه برمز مميز تم منحه نطاقًا معينًا. للبدء، أضف الوسيط التالي إلى خاصية ‎$routeMiddleware في ملف  app/Http/Kernel.php:

'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,

'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,

فحص كل النطاقات

قد تعين البرمجيّة الوسيطة scopes لمسار معين للتحقق من أن رمز الوصول الخاص بالطلب الوارد يحتوي على جميع النطاقات المدرجة:

Route::get('/orders', function () {
  // رمز الوصول تحتوي على كلّ من النطاقات “check-status” و “place-orders” ...

})->middleware('scopes:check-status,place-orders');

فحص أيّة نطاقات

قد تعين البرمجيّة الوسيطة scopes لمسار معين للتحقق من أن رمز الوصول الخاص بالطلب الوارد يحتوي على الأقل واحدا من النطاقات المدرجة:

Route::get('/orders', function () {
  // رمز الوصول تحتوي على نطاق “check-status” أو “place-orders” ...

})->middleware('scope:check-status,place-orders');

التحقق من النطاقات على نسخة رمز مُميّز

بمجرد دخول طلب مصادق عليه برمز الوصول إلى تطبيقك، قد تستمر في التحقق مما إذا كان الرمز المميز له نطاق معين، باستخدام التابع tokenCan على نسخة مستخدم (User) مصادق عليه:

use Illuminate\Http\Request;

Route::get('/orders', function (Request $request) {

   if ($request->user()->tokenCan('place-orders')) {

     //
   }
});

استخدام واجهة API الخاصة بك مع JavaScript

عند إنشاء واجهة َAPI، قد يكون من المفيد جدًّا أن تُستهلك واجهة API الخاصة بك من تطبيق JavaScript خاص بك. يسمح هذا النهج لتطوير واجهة API لتطبيقك بأن يستهلك نفس واجهة API التي تشاركها مع العالم. يمكن استخدام نفس واجهة API من خلال تطبيق الويب الخاص بك، تطبيقات الجوّال، تطبيقات الجهات الخارجية وأية SDK قد تنشرها على مُختلف مديري الحِزَمْ.

عادةً، إذا كنت ترغب في استخدام واجهة API الخاصة بك من تطبيق JavaScript، فستحتاج إلى إرسال رمز وصول إلى التطبيق يدويًا وتمريره مع كل طلب إلى التطبيق الخاص بك. ومع ذلك، يتضمن Passport برمجيّة وسيطة يمكنها التعامل مع هذا الأمر نيابةً عنك. كل ما عليك فعله هو إضافة البرمجيّة الوسيطة CreateFreshApiToken إلى مجموعة البرمجيّات الوسيطة web في الملف app/Http/Kernel.php :

'web' => [

  // وسيط آخر ...
   \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,

],

سترفق البرمجيّة الوسيطة Passport كعكة laravel_token إلى ردودك الصادرة. تحتوي هذه الكعكة على JWT مشفرة يستخدمها Passport لاستيثاق طلبات واجهة API من تطبيق JavaScript. الآن، يمكنك تقديم طلبات إلى واجهة API الخاصة بتطبيقك بدون المرور بشكل صريح برمز وصول:

axios.get('/api/user')
   .then(response => 
       console.log(response.data);

   });

عند استخدام طريقة الاستيثاق هذه، فإن سقالات javascript Laravel الافتراضية توجه Axios لإرسال ترويسات X-CSRF-TOKEN و X-Requested-With دائمًا. ومع ذلك، يجب التأكد من تضمين رمز CSRF الخاص بك في  العنصر <meta> في HTML:

window.axios.defaults.headers.common = {

   'X-Requested-With': 'XMLHttpRequest',

};

تحذير: إذا كنت تستخدم إطار عمل JavaScript مختلفًا، فيجب عليك التأكد من أنّه مضبوط لإرسال ترويسات X-CSRF-TOKEN و X-Requested-With مع كل طلب صادر.

الأحداث

يقوم Passport برفع الأحداث عند إصدار رموز الوصول ورموز للتحديث. يمكنك استخدام هذه الأحداث لتقليم أو إلغاء رموز الوصول الأخرى في قاعدة البيانات الخاصة بك. يمكنك إرفاق المستمعين بهذه الأحداث في EventServiceProvider في التطبيق الخاص بك:

/**
* تعيينات مستمع الحدث الخاصة بالتطبيق.
*
* @متغيير مصفوفة
*/

protected $listen = [

   'Laravel\Passport\Events\AccessTokenCreated' => [
       'App\Listeners\RevokeOldTokens',
   ],

   'Laravel\Passport\Events\RefreshTokenCreated' => [
       'App\Listeners\PruneOldTokens',
   ],
];

الاختبار

يمكن استخدام التابع actingAs الخاص بـ Passport لتحديد المستخدم المصادق عليه حاليًا ونطاقاته. الوسيط الأول المعطى للتابع actingAs هو نسخة المستخدم والثاني هو مصفوفة من النطاقات التي يجب منحها إلى رمز المستخدم:

public function testServerCreation()

{
   Passport::actingAs(
       factory(User::class)->create(),
       ['create-servers']
   );

   $response = $this->post('/api/create-server');
   $response->assertStatus(200);
}

مصادر