الفرق بين المراجعتين لصفحة: «Laravel/passport»
أنشأ الصفحة ب' <noinclude>{{DISPLAYTITLE:الاستثياق باستخدام واجهة API خارجية في Laravel}}</noinclude> == مقدمة == يعمل Laravel بالفعل ع...' |
ط تصحيح كلمة Authentification إلى Authentication |
||
(10 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:الاستثياق باستخدام واجهة API خارجية (API Authentication) في Laravel}}</noinclude> | |||
==مقدمة== | |||
يعمل [[Laravel]] بالفعل على تسهيل إجراء الاستيثاق عبر نماذج تسجيل الدخول التقليدية، ولكن ماذا عن الواجهات البرمجيّة (APIs)؟ تستخدم الواجهة البرمجيّة عادةً رموز (Tokens) لاستيثاق المستخدمين ولا تحتفظ بحالة الجلسة بين الطلبات. يجعل Laravel استيثاق الواجهة البرمجيّة سهلًا جدًا باستخدام واجهة API خارجية. | |||
(Laravel Passport) ، والتي توفر تطبيق خادم OAuth2 الكامل لتطبيق [[Laravel]] في غضون دقائق. الجوازات مبنية على خادم OAuth2 League المُصان بواسطة أندي ميلينغتون و سيمون هامب. | |||
(Laravel Passport) ، والتي توفر تطبيق خادم OAuth2 الكامل لتطبيق Laravel في غضون دقائق. الجوازات مبنية على خادم OAuth2 League المُصان بواسطة أندي ميلينغتون و سيمون هامب. | |||
يفترض هذا المستند أنك معتاد بالفعل على اصطلاحات OAuth2. إذا كنت لا تعرف شيئًا عن OAuth2، ففكر في التعرف على المصطلحات العامة وخصائص OAuth2 قبل المتابعة. | يفترض هذا المستند أنك معتاد بالفعل على اصطلاحات OAuth2. إذا كنت لا تعرف شيئًا عن OAuth2، ففكر في التعرف على المصطلحات العامة وخصائص OAuth2 قبل المتابعة. | ||
==التثبيت== | |||
== التثبيت == | للبدء، ثبّت الواجهة البرمجية Passport عبر Composer:<syntaxhighlight lang="php"> | ||
للبدء، ثبّت الواجهة البرمجية Passport عبر Composer: | |||
composer require laravel/passport | composer require laravel/passport | ||
</syntaxhighlight>يسجّل موفر خدمة جواز السفر (Passport) مجلد تهجير قاعدة البيانات (database migration) الخاص به مع الإطار، لذلك يجب تهجير قاعدة البيانات الخاصة بك بعد تسجيل الموفر. سوف تُنشئ عمليات تهجير جواز السفر الجداول التي يحتاجها تطبيقك لتخزين العملاء والوصول إلى الرموز (Tokens):<syntaxhighlight lang="php"> | |||
يسجّل موفر خدمة جواز السفر (Passport) مجلد تهجير قاعدة البيانات (database migration) الخاص به مع الإطار، لذلك يجب تهجير قاعدة البيانات الخاصة بك بعد تسجيل الموفر. سوف تُنشئ عمليات تهجير جواز السفر الجداول التي يحتاجها تطبيقك لتخزين العملاء والوصول إلى الرموز (Tokens): | |||
php artisan migrate | php artisan migrate | ||
</syntaxhighlight>إذا كنت لا تريد استخدام عمليات التهجير الافتراضية الخاصة بخدمة Passport، استدع التابع <code>Passport::ignoreMigrations</code> في التابع <code>register</code> الخاص بمزود الخدمة AppServiceProvider. يجوز لك تصدير عمليات التهجير الافتراضية باستخدام الأمر :<syntaxhighlight lang="php"> | |||
إذا كنت لا تريد استخدام عمليات التهجير الافتراضية الخاصة بخدمة Passport، استدع التابع Passport::ignoreMigrations في التابع register الخاص بمزود الخدمة AppServiceProvider. يجوز لك تصدير عمليات التهجير الافتراضية باستخدام الأمر | |||
php artisan vendor:publish --tag=passport-migrations | php artisan vendor:publish --tag=passport-migrations | ||
</syntaxhighlight>بعد ذلك، نفذ الأمر <code>passport:install</code>. سيُنشِئ هذا الأمر مفاتيح التشفير اللازمة لإنشاء رموز (token) آمنة. بالإضافة إلى ذلك، سيعمل الأمر على إنشاء عملاء "وصول شخصي" (personal access) و "منحة كلمة المرور" (password grant) التي ستُستخدم لتوليد رموز الوصول (access tokens):<syntaxhighlight lang="php"> | |||
بعد ذلك، نفذ الأمر passport:install. سيُنشِئ هذا الأمر مفاتيح التشفير اللازمة لإنشاء رموز (token) آمنة. بالإضافة إلى ذلك، سيعمل الأمر على إنشاء عملاء "وصول شخصي" (personal access) و "منحة كلمة المرور" (password grant) التي ستُستخدم لتوليد رموز الوصول (access tokens): | |||
php artisan passport:install | php artisan passport:install | ||
</syntaxhighlight>بعد تنفيذ هذا الأمر، أضف السمة <code>Laravel\Passport\HasApiTokens</code> إلى نموذج <code>App\User</code>. ستوفر هذه السمة عددًا قليلًا من التوابع المساعدة إلى نموذجك الذي يسمح لك بتفقد الرموز والنطاقات (scopes) للمستخدم المصادق عليه:<syntaxhighlight lang="php"> | |||
بعد تنفيذ هذا الأمر، أضف السمة Laravel\Passport\HasApiTokens إلى نموذج App\User. ستوفر هذه السمة عددًا قليلًا من التوابع المساعدة إلى نموذجك الذي يسمح لك بتفقد الرموز والنطاقات (scopes) للمستخدم المصادق عليه: | |||
< | |||
namespace App; | namespace App; | ||
use Laravel\Passport\HasApiTokens; | use Laravel\Passport\HasApiTokens; | ||
use Illuminate\Notifications\Notifiable; | use Illuminate\Notifications\Notifiable; | ||
use Illuminate\Foundation\Auth\User as Authenticatable; | use Illuminate\Foundation\Auth\User as Authenticatable; | ||
سطر 41: | سطر 25: | ||
{ | { | ||
use HasApiTokens, Notifiable; | use HasApiTokens, Notifiable; | ||
} | } | ||
</syntaxhighlight>بعد ذلك، استدع التابع <code>Passport::routes</code> داخل التابع <code>boot</code> الموجود في AuthServiceProvider الخاص بك. يُسجِّل هذا التابع المسارات اللازمة لإصدار رموز الدخول ورفض رموز الوصول والعملاء ورموز الوصول الشخصية:<syntaxhighlight lang="php"> | |||
namespace App\Providers; | namespace App\Providers; | ||
use Laravel\Passport\Passport; | use Laravel\Passport\Passport; | ||
use Illuminate\Support\Facades\Gate; | use Illuminate\Support\Facades\Gate; | ||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; | use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; | ||
سطر 61: | سطر 39: | ||
{ | { | ||
/** | /** | ||
* التعيينات السياسية للتطبيق. | * التعيينات السياسية للتطبيق. | ||
* | * | ||
* @var array | * @var array | ||
*/ | */ | ||
protected $policies = [ | protected $policies = [ | ||
'App\Model' => 'App\Policies\ModelPolicy', | 'App\Model' => 'App\Policies\ModelPolicy', | ||
]; | ]; | ||
/** | /** | ||
* تسجيل أي خدمة استيثاق / ترخيص | * تسجيل أي خدمة استيثاق / ترخيص | ||
* | * | ||
* @return void | * @return void | ||
*/ | */ | ||
سطر 91: | سطر 58: | ||
{ | { | ||
$this->registerPolicies(); | $this->registerPolicies(); | ||
Passport::routes(); | Passport::routes(); | ||
} | } | ||
} | } | ||
</syntaxhighlight>وأخيرًا، في ملف الضبط <code>config/auth.php</code>، يجب عليك تعيين driver الخاص بحارس الاستيثاق api على passport. مما يطلب من تطبيقك أن يستخدم <code>TokenGuard</code> الذي يتبع إلى Passport عند الاستيثاق من طلبيات الاستيثاق القادمة من واجهة API:<syntaxhighlight lang="json"> | |||
'guards' => [ | 'guards' => [ | ||
'web' => [ | 'web' => [ | ||
'driver' => 'session', | |||
'provider' => 'users', | |||
], | ], | ||
سطر 115: | سطر 76: | ||
'driver' => 'passport', | 'driver' => 'passport', | ||
'provider' => 'users', | 'provider' => 'users', | ||
], | ], | ||
], | |||
=== بداية سريعة للواجهة الأمامية === | </syntaxhighlight> | ||
لاستخدام مكونات Passport Vue، استخدم إطار عمل Vue. تستخدم هذه المكونات أيضًا إطار عمل Bootstrap. ومع ذلك، حتى إذا كنت لا تستخدم هذه الأدوات، فإن المكونات تعدّ مرجعًا قيمًا يفيدك عند برمجة الواجهة الخاصة بك. | ===بداية سريعة للواجهة الأمامية=== | ||
لاستخدام مكونات Passport Vue، استخدم إطار عمل Vue. تستخدم هذه المكونات أيضًا إطار عمل [[Bootstrap]]. ومع ذلك، حتى إذا كنت لا تستخدم هذه الأدوات، فإن المكونات تعدّ مرجعًا قيمًا يفيدك عند برمجة الواجهة الخاصة بك. | |||
يأتي Passport مع JSON API التي يمكنك استخدامها للسماح للمستخدمين بإنشاء عملاء ورموز وصول شخصية. ومع ذلك، يمكن أن يستغرق الأمر وقتًا طويلًا لبرمجة الواجهة الأمامية للتفاعل مع واجهات البرمجية هذه. لذلك، يشمل Passport أيضًا على مكونات Vue جاهزة التي قد تستخدمها كمثال للتنفيذ أو كنقطة انطلاق لبرمجة مكونات خاصة بك. | يأتي Passport مع JSON API التي يمكنك استخدامها للسماح للمستخدمين بإنشاء عملاء ورموز وصول شخصية. ومع ذلك، يمكن أن يستغرق الأمر وقتًا طويلًا لبرمجة الواجهة الأمامية للتفاعل مع واجهات البرمجية هذه. لذلك، يشمل Passport أيضًا على مكونات Vue جاهزة التي قد تستخدمها كمثال للتنفيذ أو كنقطة انطلاق لبرمجة مكونات خاصة بك. | ||
لنشر مكونات Passport Vue، استخدم الأمر | لنشر مكونات Passport Vue، استخدم الأمر <code>vendor:publish</code> :<syntaxhighlight lang="php"> | ||
php artisan vendor:publish --tag=passport-components | php artisan vendor:publish --tag=passport-components | ||
</syntaxhighlight>تُوضع المكونات المنشورة في المجلد <code>resources/assets/js/components</code>. بمجرد نشر المكونات، يجب عليك تسجيلهم في ملف <code>resources/assets/js/app.js</code> :<syntaxhighlight lang="php"> | |||
تُوضع المكونات المنشورة في المجلد resources/assets/js/components. بمجرد نشر المكونات، يجب عليك تسجيلهم في ملف resources/assets/js/app.js : | |||
Vue.component( | Vue.component( | ||
'passport-clients', | 'passport-clients', | ||
require('./components/passport/Clients.vue') | require('./components/passport/Clients.vue') | ||
سطر 144: | سطر 100: | ||
'passport-authorized-clients', | 'passport-authorized-clients', | ||
require('./components/passport/AuthorizedClients.vue') | require('./components/passport/AuthorizedClients.vue') | ||
سطر 152: | سطر 107: | ||
'passport-personal-access-tokens', | 'passport-personal-access-tokens', | ||
require('./components/passport/PersonalAccessTokens.vue') | require('./components/passport/PersonalAccessTokens.vue') | ||
); | ); | ||
</syntaxhighlight>بعد تسجيل المكونات، تأكد من تشغيل الأمر <code>npm run dev</code> لإعادة ترجمة أصولك. بمجرد إعادة ترجمة الأصول، يمكنك وضع المكونات في أحد نماذج تطبيقك للبدء في إنشاء عملاء ورموز وصول شخصية :<syntaxhighlight lang="xml"> | |||
<passport-clients></passport-clients> | <passport-clients></passport-clients> | ||
<passport-authorized-clients></passport-authorized-clients> | <passport-authorized-clients></passport-authorized-clients> | ||
<passport-personal-access-tokens></passport-personal-access-tokens> | <passport-personal-access-tokens></passport-personal-access-tokens> | ||
</syntaxhighlight> | |||
===نشر Passport=== | |||
عند نشر Passport على خوادم الإنتاج لأول مرة، ستحتاج على الأرجح إلى تنفيذ الأمر <code>passport:keys</code>. ينشئ هذا الأمر مفاتيح التشفير التي يحتاجها Passport لإنشاء رمز وصول. لا يُحتفظ بالمفاتيح التي أُنشِئت عادة في مصادر التحكم:<syntaxhighlight lang="php"> | |||
php artisan passport:keys | php artisan passport:keys | ||
</syntaxhighlight> | |||
== الضبط == | ==الضبط== | ||
===دورة حياة الرموز=== | |||
=== دورة حياة الرموز === | يصدر Passport افتراضيًا رموز وصول طويلة الأمد تنتهي صلاحيتها بعد مرور عام. إذا كنت ترغب في ضبط مدة صلاحية الرموز لتكون أطول أو أقصر، يمكنك استخدام التابعين <code>tokensExpireIn</code> و <code>refreshTokensExpireIn</code>. يجب استدعاء هذه التوابع من التابع <code>boot</code> الخاص بالمزود AuthServiceProvider:<syntaxhighlight lang="php"> | ||
يصدر Passport افتراضيًا رموز وصول طويلة الأمد تنتهي صلاحيتها بعد مرور عام. إذا كنت ترغب في ضبط مدة صلاحية الرموز لتكون أطول أو أقصر، يمكنك استخدام التابعين tokensExpireIn و refreshTokensExpireIn. يجب استدعاء هذه التوابع من التابع boot الخاص بالمزود AuthServiceProvider: | |||
/** | /** | ||
* تسجيل أي خدمات الاستيثاق/ الترخيص | |||
* | |||
* @return void | |||
*/ | |||
public function boot() | public function boot() | ||
سطر 190: | سطر 137: | ||
$this->registerPolicies(); | $this->registerPolicies(); | ||
Passport::routes(); | Passport::routes(); | ||
Passport::tokensExpireIn(now()->addDays(15)); | Passport::tokensExpireIn(now()->addDays(15)); | ||
Passport::refreshTokensExpireIn(now()->addDays(30)); | Passport::refreshTokensExpireIn(now()->addDays(30)); | ||
} | } | ||
== إصدار رموز الوصول == | |||
</syntaxhighlight> | |||
==إصدار رموز الوصول== | |||
يعرف معظم المطورين OAuth من خلال استعماله مع رموز الترخيص (authorization codes). عند استخدام رموز الترخيص، سيعيد تطبيق الزبون توجيه المستخدم إلى خادمك حيث سيوافق أو يرفض طلب إصدار رمز دخول مميز إلى الزبون. | يعرف معظم المطورين OAuth من خلال استعماله مع رموز الترخيص (authorization codes). عند استخدام رموز الترخيص، سيعيد تطبيق الزبون توجيه المستخدم إلى خادمك حيث سيوافق أو يرفض طلب إصدار رمز دخول مميز إلى الزبون. | ||
===إدارة العملاء=== | |||
=== إدارة العملاء === | |||
أولاً، يتعين على مطوري التطبيقات التي تحتاج إلى التفاعل مع واجهة تطبيقاتك إلى تسجيل تطبيقاتهم مع تطبيقاتك من خلال إنشاء زبون. عادةً، يتم هذا بتوفير اسم التطبيق و عنوان URL الذي يمكن لتطبيقك إعادة التوجيه إليه بعد موافقة المستخدمين على طلب الترخيص. | أولاً، يتعين على مطوري التطبيقات التي تحتاج إلى التفاعل مع واجهة تطبيقاتك إلى تسجيل تطبيقاتهم مع تطبيقاتك من خلال إنشاء زبون. عادةً، يتم هذا بتوفير اسم التطبيق و عنوان URL الذي يمكن لتطبيقك إعادة التوجيه إليه بعد موافقة المستخدمين على طلب الترخيص. | ||
====الأمر <code>passport:client</code>==== | |||
==== الأمر passport:client ==== | أبسط طريقة لإنشاء عميل هي استخدام أمر <code>passport:client Artisan</code>. يمكن استخدام هذا الأمر لإنشاء عملاء خاصين بك لاختبار وظائف OAuth2. عند تنفيذ أمر <code>client</code>، يطالبك Passport بمزيد من المعلومات حول العميل و يزودك بمعرّف عميل ID و كلمة سرية:<syntaxhighlight lang="php"> | ||
أبسط طريقة لإنشاء عميل هي استخدام أمر passport:client Artisan. يمكن استخدام هذا الأمر لإنشاء عملاء خاصين بك لاختبار وظائف OAuth2. عند تنفيذ أمر | |||
php artisan passport:client | php artisan passport:client | ||
</syntaxhighlight> | |||
====واجهة (API) JSON==== | |||
نظرًا لأن مستخدمي تطبيقك لن يتمكنوا من استخدام أمر client، يوفر Passport واجهة [[JSON]] التي قد تستخدمها لإنشاء عملاء. هذا يوفر عليك عناء الاضطرار إلى برمجة وحدات التحكم (Controllers) يدويًا لإنشاء، أو تحديث، أو حذف العملاء. | |||
ومع ذلك، ستحتاج إلى إقران واجهة [[JSON]] التي تتبع إلى Passport مع الواجهة الأمامية الخاصة بك لتوفير لوحة تحكم للمستخدمين لإدارة عملائهم. في ما يلي، سنراجع جميع نقاط نهاية الواجهة API لإدارة العملاء. للسهولة، سنستخدم Axios لإرسال طلبيات HTTP إلى نقاط النهاية. | |||
ومع ذلك، ستحتاج إلى إقران واجهة JSON التي تتبع إلى Passport مع الواجهة الأمامية الخاصة بك لتوفير لوحة تحكم للمستخدمين لإدارة عملائهم. في ما يلي، سنراجع جميع نقاط نهاية الواجهة API لإدارة العملاء. للسهولة، سنستخدم Axios لإرسال طلبيات HTTP إلى نقاط النهاية. | |||
'''ملاحظة:''' إذا كنت لا ترغب في برمجة واجهة إدارة العميل بالكامل بنفسك، فيمكنك استخدام بدء سريع للواجهة الأمامية للحصول على واجهة أمامية كاملة في غضون دقائق. | |||
=====<code>GET /oauth/clients</code>===== | |||
يقوم هذا المسار بإرجاع كافة العملاء للمستخدم المصادق عليه. هذا مفيد بشكل أساسي لإدراج كافة عملاء المستخدم بحيث يمكنه تعديلها أو حذفها:<syntaxhighlight lang="php"> | |||
axios.get('/oauth/clients') | axios.get('/oauth/clients') | ||
.then(response => { | .then(response => { | ||
console.log(response.data); | console.log(response.data); | ||
}); | }); | ||
===== POST /oauth/clients ===== | |||
</syntaxhighlight> | |||
=====<code>POST /oauth/clients</code>===== | |||
يستخدم هذا المسار لإنشاء عملاء جدد. ويتطلب معلومتين: اسم العميل (name) وعنوان URL لإعادة التوجيه (redirect). عنوان URL هو المكان الذي سيعاد توجيه المستخدم إليه بعد الموافقة على طلب الترخيص أو رفضه. | يستخدم هذا المسار لإنشاء عملاء جدد. ويتطلب معلومتين: اسم العميل (name) وعنوان URL لإعادة التوجيه (redirect). عنوان URL هو المكان الذي سيعاد توجيه المستخدم إليه بعد الموافقة على طلب الترخيص أو رفضه. | ||
عند إنشاء عميل، يتم إصدار معرف العميل وسر العميل. يتم استخدام هذه القيم عند طلب رمز الوصول من تطبيقك. يُعيد مسار إنشاء العميل نسخة العميل الجديد: | عند إنشاء عميل، يتم إصدار معرف العميل وسر العميل. يتم استخدام هذه القيم عند طلب رمز الوصول من تطبيقك. يُعيد مسار إنشاء العميل نسخة العميل الجديد:<syntaxhighlight lang="php"> | ||
onst data = { | onst data = { | ||
name: 'Client Name', | name: 'Client Name', | ||
redirect: 'http://example.com/callback' | |||
redirect: ' | |||
}; | }; | ||
axios.post('/oauth/clients', data) | axios.post('/oauth/clients', data) | ||
.then(response => { | .then(response => { | ||
console.log(response.data); | console.log(response.data); | ||
}) | }) | ||
سطر 252: | سطر 187: | ||
// عدّد الأخطاء عند الإجابة ... | // عدّد الأخطاء عند الإجابة ... | ||
}); | }); | ||
</syntaxhighlight> | |||
=====<code>{PUT /oauth/clients/{client-id</code>===== | |||
يستخدم هذا المسار لتحديث العملاء. يتطلب معلومتين: اسم العميل وعنوان URL لإعادة التوجيه. عنوان URL هو المكان الذي سيعاد توجيه المستخدم إليه بعد الموافقة على طلب الترخيص أو رفضه. سيعيد المسار نسخة العميل المُحدّثة:<syntaxhighlight lang="php"> | |||
const data = { | const data = { | ||
name: 'New Client Name', | name: 'New Client Name', | ||
redirect: 'http://example.com/callback' | |||
redirect: ' | |||
}; | }; | ||
axios.put('/oauth/clients/' + clientId, data) | axios.put('/oauth/clients/' + clientId, data) | ||
.then(response => { | .then(response => { | ||
console.log(response.data); | console.log(response.data); | ||
}) | }) | ||
.catch (response => { | .catch (response => { | ||
// List errors on response... | // List errors on response... | ||
}); | }); | ||
</syntaxhighlight> | |||
=====<code>{DELETE /oauth/clients/{client-id</code>===== | |||
يستخدم هذا المسار لحذف العملاء:<syntaxhighlight lang="php"> | |||
axios.delete('/oauth/clients/' + clientId) | axios.delete('/oauth/clients/' + clientId) | ||
.then(response => { | .then(response => { | ||
// | // | ||
}); | }); | ||
</syntaxhighlight> | |||
===طلب الرموز=== | |||
====إعادة التوجيه للحصول على الترخيص==== | |||
بمجرد إنشاء عميل، يمكن للمطورين استخدام مُعرّف العميل وسرّه لطلب رمز الترخيص ورمز الوصول من تطبيقك. أولاً، يجب أن يجري التطبيق المُستهلِك طلب إعادة توجيه إلى مسار <code>oauth/authorize</code> الخاص بتطبيقك كما يلي:<syntaxhighlight lang="php"> | |||
Route::get('/redirect', function () { | Route::get('/redirect', function () { | ||
سطر 301: | سطر 227: | ||
'client_id' => 'client-id', | 'client_id' => 'client-id', | ||
'redirect_uri' => 'http://example.com/callback', | |||
'redirect_uri' => ' | |||
'response_type' => 'code', | 'response_type' => 'code', | ||
'scope' => '', | |||
'scope' = | |||
]); | ]); | ||
return redirect(' | return redirect('http://your-app.com/oauth/authorize?'.$query); | ||
}); | }); | ||
==== الموافقة على الطلب ==== | </syntaxhighlight>ملاحظة: تذكر، المسار <code>/oauth/authorize</code> معرف مسبقًا بواسطة التابع <code>Passport::routes</code>. لست بحاجة إلى تحديد هذا المسار يدويًا. | ||
====الموافقة على الطلب==== | |||
عند تلقي طلبات الترخيص، سيعرض Passport تلقائيًا قالبًا على المستخدم يسمح له بالموافقة على أي طلب للترخيص أو رفضه. إذا وافق على الطلب، فسيعاد التوجيه إلى redirect_uri الذي حُدّد من خلال التطبيق المُستهلِك. يجب أن يتطابق redirect_uri مع عنوان URL redirect الذي حُدّد عند إنشاء العميل. | عند تلقي طلبات الترخيص، سيعرض Passport تلقائيًا قالبًا على المستخدم يسمح له بالموافقة على أي طلب للترخيص أو رفضه. إذا وافق على الطلب، فسيعاد التوجيه إلى redirect_uri الذي حُدّد من خلال التطبيق المُستهلِك. يجب أن يتطابق redirect_uri مع عنوان URL redirect الذي حُدّد عند إنشاء العميل. | ||
إذا كنت ترغب في تخصيص شاشة الموافقة على الترخيص، فيمكنك نشر واجهات Passport باستخدام أمر vendor:publish Artisan. ستوضع الواجهة المنشورة في resources/views/vendor/passport : | إذا كنت ترغب في تخصيص شاشة الموافقة على الترخيص، فيمكنك نشر واجهات Passport باستخدام أمر <code>vendor:publish Artisan.</code> ستوضع الواجهة المنشورة في <code>resources/views/vendor/passport</code> :<syntaxhighlight lang="php"> | ||
php artisan vendor:publish --tag=passport-views | php artisan vendor:publish --tag=passport-views | ||
</syntaxhighlight> | |||
====تحويل رموز الترخيص إلى رموز وصول==== | |||
إذا وافق المستخدم على طلب الترخيص، فسيعاد توجيهه مرة أخرى إلى التطبيق المُستهلِك. يجب على المُستهلِك بعد ذلك إصدار طلب POST إلى تطبيقك لطلب رمز وصول. يجب أن يتضمن الطلب رمز الترخيص الذي أُصدر من تطبيقك عندما وافق المستخدم على طلب الترخيص. في هذا المثال، سنستخدم مكتبة Guzzle HTTP لإجراء طلب POST : | إذا وافق المستخدم على طلب الترخيص، فسيعاد توجيهه مرة أخرى إلى التطبيق المُستهلِك. يجب على المُستهلِك بعد ذلك إصدار طلب POST إلى تطبيقك لطلب رمز وصول. يجب أن يتضمن الطلب رمز الترخيص الذي أُصدر من تطبيقك عندما وافق المستخدم على طلب الترخيص. في هذا المثال، سنستخدم مكتبة Guzzle HTTP لإجراء طلب POST :<syntaxhighlight lang="php"> | ||
Route::get('/callback', function (Request $request) { | Route::get('/callback', function (Request $request) { | ||
$http = new GuzzleHttp\Client; | $http = new GuzzleHttp\Client; | ||
$response = $http->post('http://your-app.com/oauth/token', [ | |||
$response = $http->post(' | |||
'form_params' => [ | 'form_params' => [ | ||
'grant_type' => 'authorization_code', | 'grant_type' => 'authorization_code', | ||
'client_id' => 'client-id', | 'client_id' => 'client-id', | ||
'client_secret' => 'client-secret', | 'client_secret' => 'client-secret', | ||
'redirect_uri' => 'http://example.com/callback', | |||
'redirect_uri' => ' | |||
'code' => $request->code, | 'code' => $request->code, | ||
], | ], | ||
]); | ]); | ||
return json_decode((string) $response->getBody(), true); | return json_decode((string) $response->getBody(), true); | ||
}); | }); | ||
</syntaxhighlight>يعيد المسار <code>/oauth/token</code> رد JSON يحتوي على رموز الوصول <code>access_token</code>، <code>refresh_token</code>، وخاصية <code>expires_in</code>. تحتوي خاصية <code>expires_in</code> على وقت نهاية صلاحية رمز الوصول. | |||
ملاحظة: كما في مسار <code>oauth/authorize/</code>، يُعرّف المسار <code>/oauth/token</code> من خلال التابع <code>Passport::routes.</code> لا حاجة لتحديد هذا المسار يدويًا. | |||
===تحديث الرموز=== | |||
إذا كان تطبيقك يصدر رموز وصول قصيرة العمر، سيحتاج المستخدمون إلى تحديث رموز الوصول الخاصة بهم عبر رمز التحديث الذي وُفّر عند إصدار رمز الوصول. في هذا المثال، سوف نستخدم مكتبة Guzzle HTTP لتحديث الرمز:<syntaxhighlight lang="php"> | |||
$http = new GuzzleHttp\Client; | $http = new GuzzleHttp\Client; | ||
$response = $http->post('http://your-app.com/oauth/token', [ | |||
$response = $http->post(' | |||
'form_params' => [ | 'form_params' => [ | ||
'grant_type' => 'refresh_token', | 'grant_type' => 'refresh_token', | ||
'refresh_token' => 'the-refresh-token', | 'refresh_token' => 'the-refresh-token', | ||
'client_id' => 'client-id', | 'client_id' => 'client-id', | ||
'client_secret' => 'client-secret', | 'client_secret' => 'client-secret', | ||
'scope' => '', | |||
'scope' = | |||
], | ], | ||
]); | ]); | ||
return json_decode((string) $response->getBody(), true); | return json_decode((string) $response->getBody(), true); | ||
== رموز منحة كلمة المرور Password Grant Tokens == | </syntaxhighlight>سيعرض هذا المسار /oauth/token رد JSON التي تحتوي على سمات <code>access_token</code>، و <code>refresh_token</code>و <code>expires_in</code>. تحتوي السمة <code>expires_in</code> على عدد الثواني حتى تنتهي صلاحية رمز الوصول. | ||
==رموز منحة كلمة المرور Password Grant Tokens== | |||
تسمح منحة كلمة مرور OAuth2 للطرف الأول لعملائك، مثل تطبيق الجوال، بالحصول على رمز وصول باستخدام عنوان البريد الإلكتروني أو اسم المستخدم وكلمة المرور. يتيح لك هذا إصدار رموز الدخول بشكل آمن إلى عملاء الطرف الأول دون مطالبة المستخدمين بالانتقال عبر رمز إعادة توجيه الترخيص OAuth2 بالكامل. | تسمح منحة كلمة مرور OAuth2 للطرف الأول لعملائك، مثل تطبيق الجوال، بالحصول على رمز وصول باستخدام عنوان البريد الإلكتروني أو اسم المستخدم وكلمة المرور. يتيح لك هذا إصدار رموز الدخول بشكل آمن إلى عملاء الطرف الأول دون مطالبة المستخدمين بالانتقال عبر رمز إعادة توجيه الترخيص OAuth2 بالكامل. | ||
===إنشاء عميل منحة كلمة المرور=== | |||
=== إنشاء عميل منحة كلمة المرور === | قبل أن يتمكن تطبيقك من إصدار رموز عبر منحة كلمة المرور، تحتاج إلى إنشاء عميل لمنح كلمة المرور. يمكنك القيام بذلك باستخدام الأمر <code>passport:client</code> مع الخيار <code>--password</code>. إذا كنت قد نفّذت الأمر <code>passport:install</code>، فلن تحتاج إلى تنفيذ هذا الأمر:<syntaxhighlight lang="php"> | ||
قبل أن يتمكن تطبيقك من إصدار رموز عبر منحة كلمة المرور، تحتاج إلى إنشاء عميل لمنح كلمة المرور. يمكنك القيام بذلك باستخدام الأمر passport:client مع الخيار --password. إذا كنت قد نفّذت الأمر passport: | |||
php artisan passport:client --password | php artisan passport:client --password | ||
=== طلب الرموز === | </syntaxhighlight> | ||
بمجرد إنشاء عميل منحة كلمة المرور، يمكنك طلب رمز وصول عن طريق إصدار طلب POST إلى المسار /oauth/token باستخدام عنوان البريد الإلكتروني وكلمة المرور الخاصين بالمستخدم. تذكر، تم تسجيل هذا المسار بواسطة التابع Passport::routes لذلك لا حاجة لتعريفه يدويًّا. إذا كان الطلب ناجحًا، سوف تتلقى access_token و refresh_token في رد JSON من الخادم : | ===طلب الرموز=== | ||
بمجرد إنشاء عميل منحة كلمة المرور، يمكنك طلب رمز وصول عن طريق إصدار طلب POST إلى المسار <code>/oauth/token</code> باستخدام عنوان البريد الإلكتروني وكلمة المرور الخاصين بالمستخدم. تذكر، تم تسجيل هذا المسار بواسطة التابع <code>Passport::routes</code> لذلك لا حاجة لتعريفه يدويًّا. إذا كان الطلب ناجحًا، سوف تتلقى <code>access_token</code> و <code>refresh_token</code> في رد JSON من الخادم :<syntaxhighlight lang="php"> | |||
$http = new GuzzleHttp\Client; | $http = new GuzzleHttp\Client; | ||
$response = $http->post('http://your-app.com/oauth/token', [ | |||
$response = $http->post(' | |||
'form_params' => [ | 'form_params' => [ | ||
'grant_type' => 'password', | 'grant_type' => 'password', | ||
'client_id' => 'client-id', | 'client_id' => 'client-id', | ||
'client_secret' => 'client-secret', | 'client_secret' => 'client-secret', | ||
'username' => 'taylor@laravel.com', | 'username' => 'taylor@laravel.com', | ||
'password' => 'my-password', | 'password' => 'my-password', | ||
'scope' => '', | |||
'scope' = | |||
], | ], | ||
]); | ]); | ||
return json_decode((string) $response->getBody(), true); | return json_decode((string) $response->getBody(), true); | ||
=== طلب جميع النطاقات === | </syntaxhighlight>ملاحظة: تذكر أن عمر رموز الوصول طويل افتراضيًا. ومع ذلك، أنت حر في ضبط الحد الأقصى لعمر رموز الوصول إذا لزم الأمر. | ||
عند استخدام منحة كلمة المرور، قد ترغب في ترخيص الرمز لجميع النطاقات التي يدعمها تطبيقك. يمكنك القيام بذلك عن طريق طلب النطاق *. إذا طلبت النطاق *، فسيرجع التابع can على نسخة الرمز true القيمة دومًا. قد يُعيّن هذا النطاق فقط لرمز أُصدر باستخدام منح كلمة المرور: | ===طلب جميع النطاقات=== | ||
عند استخدام منحة كلمة المرور، قد ترغب في ترخيص الرمز لجميع النطاقات التي يدعمها تطبيقك. يمكنك القيام بذلك عن طريق طلب النطاق *. إذا طلبت النطاق *، فسيرجع التابع can على نسخة الرمز <code>true</code> القيمة دومًا. قد يُعيّن هذا النطاق فقط لرمز أُصدر باستخدام منح كلمة المرور:<syntaxhighlight lang="php"> | |||
$response = $http->post(' | $response = $http->post('http://your-app.com/oauth/token', [ | ||
'form_params' => [ | 'form_params' => [ | ||
'grant_type' => 'password', | 'grant_type' => 'password', | ||
'client_id' => 'client-id', | 'client_id' => 'client-id', | ||
'client_secret' => 'client-secret', | 'client_secret' => 'client-secret', | ||
'username' => 'taylor@laravel.com', | 'username' => 'taylor@laravel.com', | ||
'password' => 'my-password', | 'password' => 'my-password', | ||
'scope' => '*', | 'scope' => '*', | ||
], | ], | ||
]); | ]); | ||
</syntaxhighlight> | |||
==منح رموز ضمنية== | |||
المنحة الضمنية مشابهة لمنح رمز الترخيص، ومع ذلك، يُعاد الرمز إلى العميل دون تبادل رمز الترخيص. تُستخدم هذه المنحة بشكلٍ شائع لتطبيقات <code>JavaScript</code> أو تطبيقات الجوّال حيث لا يمكن تخزين بيانات اعتماد العميل بأمان. لتمكين المنحة، استدعِ التابع <code>enableImplicitGrant</code> في <code>AuthServiceProvider</code> الخاص بك:<syntaxhighlight lang="php"> | |||
/** | /** | ||
* تسجيل أي خدمة استيثاق / ترخيص | |||
* | |||
* @return void | |||
*/ | |||
public function boot() | public function boot() | ||
{ | { | ||
$this->registerPolicies(); | $this->registerPolicies(); | ||
Passport::routes(); | Passport::routes(); | ||
Passport::enableImplicitGrant(); | Passport::enableImplicitGrant(); | ||
} | } | ||
</syntaxhighlight>بمجرد تمكين المنحة، قد يستخدم المطورون مُعرّف العميل الخاص بهم لطلب رمز وصول من تطبيقك. يجب أن يقوم التطبيق المُستهلِك بإجراء طلب إعادة توجيه إلى مسار <code>/oauth/authorize</code> الخاص بتطبيقك كما يلي:<syntaxhighlight lang="php"> | |||
Route::get('/redirect', function () { | Route::get('/redirect', function () { | ||
سطر 477: | سطر 359: | ||
'client_id' => 'client-id', | 'client_id' => 'client-id', | ||
'redirect_uri' => 'http://example.com/callback', | |||
'redirect_uri' => ' | |||
'response_type' => 'token', | 'response_type' => 'token', | ||
'scope' => '', | |||
'scope' = | |||
]); | ]); | ||
return redirect(' | return redirect('http://your-app.com/oauth/authorize?'.$query); | ||
}); | }); | ||
</syntaxhighlight>ملاحظة: تذكر أن المسار <code>/oauth/authorize</code> مُعرّف مسبقًا بواسطة التابع <code>Passport::route</code>. لست بحاجة إلى تعريف هذا المسار يدويًا. | |||
==رموز منح معلومات اعتماد العميل== | |||
منحة بيانات اعتماد العميل مناسبة لاستيثاق جهاز لجهاز. على سبيل المثال، قد تستخدم هذه المنحة في مهمة مجدولة تُنفِّذ مهام الصيانة على واجهة API. لاستخدام هذه الطريقة، تحتاج أولًا إلى إضافة وسيط جديد إلى <code>$routeMiddleware</code> في <code>app/Http/Kernel.php</code> :<syntaxhighlight lang="php"> | |||
use Laravel\Passport\Http\Middleware\CheckClientCredentials; | use Laravel\Passport\Http\Middleware\CheckClientCredentials; | ||
protected $routeMiddleware = [ | protected $routeMiddleware = [ | ||
'client' => CheckClientCredentials::class, | |||
]; | ]; | ||
</syntaxhighlight>ثم اربط هذا الوسيط بمسار :<syntaxhighlight lang="php"> | |||
Route::get('/user', function(Request $request) { | Route::get('/user', function(Request $request) { | ||
... | ... | ||
})->middleware('client'); | })->middleware('client'); | ||
</syntaxhighlight>للحصول على رمز مميّز، قدّم طلبًا لنقطة النهاية <code>oauth/token</code>:<syntaxhighlight lang="php"> | |||
$guzzle = new GuzzleHttp\Client; | $guzzle = new GuzzleHttp\Client; | ||
$response = $guzzle->post('http://your-app.com/oauth/token', [ | |||
$response = $guzzle->post(' | |||
'form_params' => [ | 'form_params' => [ | ||
'grant_type' => 'client_credentials', | 'grant_type' => 'client_credentials', | ||
'client_id' => 'client-id', | 'client_id' => 'client-id', | ||
'client_secret' => 'client-secret', | 'client_secret' => 'client-secret', | ||
'scope' => 'your-scope', | 'scope' => 'your-scope', | ||
], | ], | ||
]); | ]); | ||
return json_decode((string) $response->getBody(), true)['access_token']; | return json_decode((string) $response->getBody(), true)['access_token']; | ||
== رموز الوصول الشخصية == | |||
</syntaxhighlight> | |||
==رموز الوصول الشخصية== | |||
في بعض الأحيان، قد يرغب المستخدمون في إصدار رموز الوصول لأنفسهم دون المرور بإعادة التوجيه العادي لرمز الترخيص. يمكن للسماح للمستخدمين بإصدار الرموز المميزة لأنفسهم عبر واجهة المستخدم الخاصة بتطبيقك أن يكون مفيدًا في السماح للمستخدمين بتجربة واجهة API الخاصة بك أو قد يكون بمثابة أسلوب أبسط لإصدار رموز الوصول بشكل عام. | في بعض الأحيان، قد يرغب المستخدمون في إصدار رموز الوصول لأنفسهم دون المرور بإعادة التوجيه العادي لرمز الترخيص. يمكن للسماح للمستخدمين بإصدار الرموز المميزة لأنفسهم عبر واجهة المستخدم الخاصة بتطبيقك أن يكون مفيدًا في السماح للمستخدمين بتجربة واجهة API الخاصة بك أو قد يكون بمثابة أسلوب أبسط لإصدار رموز الوصول بشكل عام. | ||
تحذير: رموز الوصول الشخصية دائما طويلة العمر. لا يُعدّل عمرها عند استخدام التابعين tokensExpireIn أو refreshTokensExpireIn. | تحذير: رموز الوصول الشخصية دائما طويلة العمر. لا يُعدّل عمرها عند استخدام التابعين <code>tokensExpireIn</code> أو <code>refreshTokensExpireIn</code>. | ||
===إنشاء عميل الوصول الشخصي=== | |||
=== إنشاء عميل الوصول الشخصي === | قبل أن يتمكن تطبيقك من إصدار رموز وصول شخصية، تحتاج إلى إنشاء عميل وصول شخصي. يمكنك ذلك باستخدام الأمر <code>passport:client</code> مع الخيار <code>--personal</code>. إذا كنت قد نفّذت بالفعل أمر <code>passport:install</code>، فلن تحتاج إلى تنفيذ هذا الأمر:<syntaxhighlight lang="php"> | ||
قبل أن يتمكن تطبيقك من إصدار رموز وصول شخصية، تحتاج إلى إنشاء عميل وصول شخصي. يمكنك ذلك باستخدام الأمر passport:client مع الخيار --personal. إذا كنت قد نفّذت بالفعل أمر passport: | |||
php artisan passport:client --personal | php artisan passport:client --personal | ||
</syntaxhighlight> | |||
=== إدارة رموز الوصول الشخصية === | ===إدارة رموز الوصول الشخصية=== | ||
بمجرد إنشاء عميل وصول شخصي، يجوز لك إصدار الرموز المميزة لمُستخدِم مُعين باستخدام التابع createToken على نسخة نموذج User. يقبل التابع createToken اسم الرمز المميز كوسيط أول له (argument) ومصفوفة اختيارية من النطاقات كوسيط ثان له: | بمجرد إنشاء عميل وصول شخصي، يجوز لك إصدار الرموز المميزة لمُستخدِم مُعين باستخدام التابع <code>createToken</code> على نسخة نموذج <code>User</code>. يقبل التابع <code>createToken</code> اسم الرمز المميز كوسيط أول له (argument) ومصفوفة اختيارية من النطاقات كوسيط ثان له:<syntaxhighlight lang="php"> | ||
$user = App\User::find(1); | $user = App\User::find(1); | ||
// إنشاء رمز مميز بدون نطاقات ... | // إنشاء رمز مميز بدون نطاقات ... | ||
$token = $user->createToken('Token Name')->accessToken; | $token = $user->createToken('Token Name')->accessToken; | ||
// إنشاء رمز مميز بالنطاقات ... | // إنشاء رمز مميز بالنطاقات ... | ||
$token = $user->createToken('My Token', ['place-orders'])->accessToken; | |||
==== واجهة API JSON ==== | </syntaxhighlight> | ||
====واجهة API JSON==== | |||
يتضمن Passport أيضًا واجهة API JSON لإدارة رموز الوصول الشخصية. يمكنك إقران ذلك مع الواجهة الأمامية الخاصة بك لتزويد المستخدمين بلوحة تحكم لإدارة رموز الوصول الشخصية. فيما يلي، سنراجع جميع نقاط نهاية الواجهة API لإدارة رموز الوصول الشخصية. للسهولة، سنستخدم Axios لإنشاء طلبيات HTTP إلى نقاط النهاية. | يتضمن Passport أيضًا واجهة API JSON لإدارة رموز الوصول الشخصية. يمكنك إقران ذلك مع الواجهة الأمامية الخاصة بك لتزويد المستخدمين بلوحة تحكم لإدارة رموز الوصول الشخصية. فيما يلي، سنراجع جميع نقاط نهاية الواجهة API لإدارة رموز الوصول الشخصية. للسهولة، سنستخدم Axios لإنشاء طلبيات HTTP إلى نقاط النهاية. | ||
ملاحظة: إذا لم ترغب في برمجة واجهة رموز الوصول الشخصية بنفسك، فيمكنك استخدام بدء سريع للواجهة الأمامية للحصول على واجهة أمامية كاملة في غضون دقائق. | ملاحظة: إذا لم ترغب في برمجة واجهة رموز الوصول الشخصية بنفسك، فيمكنك استخدام بدء سريع للواجهة الأمامية للحصول على واجهة أمامية كاملة في غضون دقائق. | ||
=====<code>GET /oauth/scopes</code>===== | |||
===== GET /oauth/scopes ===== | يعيد هذا المسار جميع النطاقات المعرفة من أجل التطبيق الخاص بك. يمكنك استخدام هذا المسار لسرد النطاقات التي يمكن للمستخدم تعيينها إلى رمز وصول شخصي:<syntaxhighlight lang="php"> | ||
يعيد هذا المسار جميع النطاقات المعرفة من أجل التطبيق الخاص بك. يمكنك استخدام هذا المسار لسرد النطاقات التي يمكن للمستخدم تعيينها إلى رمز وصول شخصي: | |||
axios.get('/oauth/scopes') | axios.get('/oauth/scopes') | ||
.then(response => { | .then(response => { | ||
console.log(response.data); | console.log(response.data); | ||
}); | }); | ||
</syntaxhighlight> | |||
=====<code>GET /oauth/personal-access-tokens</code>===== | |||
يعيد هذا المسار جميع رموز الوصول الشخصية التي أنشأها المستخدم المصادق عليه. يعد هذا مفيدًا بشكل أساسي لسرد جميع الرموز المميزة للمستخدم بحيث يمكنه تعديلها أو حذفها:<syntaxhighlight lang="php"> | |||
axios.get('/oauth/personal-access-tokens') | axios.get('/oauth/personal-access-tokens') | ||
.then(response => { | .then(response => { | ||
console.log(response.data); | console.log(response.data); | ||
}); | }); | ||
</syntaxhighlight> | |||
=====<code>POST /oauth/personal-access-tokens</code>===== | |||
ينشئ هذا المسار رموز وصول شخصية جديدة. يتطلب ذلك وجود معلومتين: اسم الرمز المميز و النطاقات (scopes) التي يجب تعيينها إلى الرمز المميز :<syntaxhighlight lang="php"> | |||
const data = { | const data = { | ||
name: 'Token Name', | |||
scopes: [] | scopes: [] | ||
سطر 595: | سطر 457: | ||
axios.post('/oauth/personal-access-tokens', data) | axios.post('/oauth/personal-access-tokens', data) | ||
.then(response => { | .then(response => { | ||
console.log(response.data.accessToken); | console.log(response.data.accessToken); | ||
}) | }) | ||
.catch (response => { | .catch (response => { | ||
/ /عدّد الأخطاء عند الإجابة... | / /عدّد الأخطاء عند الإجابة... | ||
}); | }); | ||
</syntaxhighlight> | |||
==== DELETE /oauth/personal-access-tokens/{token-id} ==== | ====<code>DELETE /oauth/personal-access-tokens/{token-id}</code>==== | ||
يُستخدم هذا المسار لحذف رموز الوصول الشخصية: | يُستخدم هذا المسار لحذف رموز الوصول الشخصية:<syntaxhighlight lang="php"> | ||
axios.delete('/oauth/personal-access-tokens/' + tokenId); | axios.delete('/oauth/personal-access-tokens/' + tokenId); | ||
</syntaxhighlight> | |||
== حماية المسارات == | ==حماية المسارات== | ||
===عن طريق برمجيّة وسيطة=== | |||
=== عن طريق برمجيّة وسيطة === | يتضمن Passport حارس استيثاق يتحقق من رموز الوصول الخاصة بالطلبات الواردة. بمجرد ضبطك للحارس api لاستخدام مُشغّل passport، تحتاج فقط إلى تحديد البرمجيّة الوسيطة <code>auth:api</code> على أي مسار يتطلب رمز وصول صالح:<syntaxhighlight lang="php"> | ||
يتضمن Passport حارس استيثاق يتحقق من رموز الوصول الخاصة بالطلبات الواردة. بمجرد ضبطك للحارس api لاستخدام مُشغّل passport، تحتاج فقط إلى تحديد البرمجيّة الوسيطة auth:api على أي مسار يتطلب رمز وصول صالح: | |||
oute::get('/user', function () { | oute::get('/user', function () { | ||
// | |||
})->middleware('auth:api'); | })->middleware('auth:api'); | ||
</syntaxhighlight> | |||
===تمرير رموز الوصول=== | |||
عند استدعاء المسارات المحمية بواسطة Passport، يجب على مستعملي واجهة API الخاصة بتطبيقاتك تحديد رموز الوصول الخاص بهم كرمز Bearer في عنوان Authorization الخاص بطلبهم. على سبيل المثال، عند استخدام مكتبة Guzzle HTTP:<syntaxhighlight lang="php"> | |||
$response = $client->request('GET', '/api/user', [ | $response = $client->request('GET', '/api/user', [ | ||
'headers' => [ | 'headers' => [ | ||
'Accept' => 'application/json', | 'Accept' => 'application/json', | ||
'Authorization' => 'Bearer '.$accessToken, | 'Authorization' => 'Bearer '.$accessToken, | ||
], | ], | ||
]); | ]); | ||
=== تعريف النطاقات === | </syntaxhighlight> | ||
==نطاقات الرمز== | |||
===تعريف النطاقات=== | |||
تسمح النطاقات لزبائن واجهة API الخاصة بك بطلب مجموعة محددة من الرُخص عند طلب ترخيص للوصول إلى الحساب. على سبيل المثال، إذا كنت تنشئ تطبيقًا للتجارة الإلكترونية، فلن يحتاج جميع مستخدمي واجهة API إلى القدرة على تقديم طلبات. بدلًا من ذلك، يمكنك أن تسمح للمستخدمين بطلب الترخيص للوصول فقط إلى حالة شحن الطلبات. بعبارة أخرى، تتيح النطاقات لمستخدمي تطبيقك تحديد الأعمال التي يمكن أن يقدّمها تطبيق تابع لجهة خارجية نيابةً عنهم. | تسمح النطاقات لزبائن واجهة API الخاصة بك بطلب مجموعة محددة من الرُخص عند طلب ترخيص للوصول إلى الحساب. على سبيل المثال، إذا كنت تنشئ تطبيقًا للتجارة الإلكترونية، فلن يحتاج جميع مستخدمي واجهة API إلى القدرة على تقديم طلبات. بدلًا من ذلك، يمكنك أن تسمح للمستخدمين بطلب الترخيص للوصول فقط إلى حالة شحن الطلبات. بعبارة أخرى، تتيح النطاقات لمستخدمي تطبيقك تحديد الأعمال التي يمكن أن يقدّمها تطبيق تابع لجهة خارجية نيابةً عنهم. | ||
يمكنك تعريف نطاقات واجهة API الخاصة بك باستخدام التابع Passport::tokensCan في التابع boot لمزود الخدمة AuthServiceProvider الخاص بك. يقبل التابع tokensCan مصفوفة من أسماء النطاق وأوصاف النطاق. قد يكون وصف النطاق هو أي شيء تريده ويتم عرضه للمستخدمين على شاشة اعتماد الترخيص: | يمكنك تعريف نطاقات واجهة API الخاصة بك باستخدام التابع <code>Passport::tokensCan</code> في التابع <code>boot</code> لمزود الخدمة AuthServiceProvider الخاص بك. يقبل التابع <code>tokensCan</code> مصفوفة من أسماء النطاق وأوصاف النطاق. قد يكون وصف النطاق هو أي شيء تريده ويتم عرضه للمستخدمين على شاشة اعتماد الترخيص:<syntaxhighlight lang="php"> | ||
use Laravel\Passport\Passport; | use Laravel\Passport\Passport; | ||
سطر 651: | سطر 501: | ||
'place-orders' => 'Place orders', | 'place-orders' => 'Place orders', | ||
'check-status' => 'Check order status', | 'check-status' => 'Check order status', | ||
]); | ]); | ||
</syntaxhighlight> | |||
===تعيين النطاقات للرموز=== | |||
====عند طلب رموز الترخيص==== | |||
عند طلب رمز الوصول باستخدام منحة رمز الترخيص، يجب على المستهلكين تحديد نطاقاتهم المرغوبة كمعامل لاستعلام النطاق. يجب أن يكون معامل النطاق قائمة من النطاقات مفصولة بفراغات:<syntaxhighlight lang="php"> | |||
Route::get('/redirect', function () { | Route::get('/redirect', function () { | ||
سطر 666: | سطر 515: | ||
'client_id' => 'client-id', | 'client_id' => 'client-id', | ||
'redirect_uri' => 'http://example.com/callback', | |||
'redirect_uri' => ' | |||
'response_type' => 'code', | 'response_type' => 'code', | ||
'scope' => 'place-orders check-status', | 'scope' => 'place-orders check-status', | ||
]); | ]); | ||
return redirect(' | return redirect('http://your-app.com/oauth/authorize?'.$query); | ||
}); | }); | ||
</syntaxhighlight> | |||
====عند إصدار رموز الوصول الشخصية==== | |||
إذا كنت تصدر رموز وصول شخصية باستخدام التابع <code>createToken</code> الخاص بنموذج <code>User</code>، فيمكنك تمرير مصفوفة من النطاقات المطلوبة كوسيط ثان إلى الطريقة :<syntaxhighlight lang="php"> | |||
$token = $user->createToken('My Token', ['place-orders'])->accessToken; | $token = $user->createToken('My Token', ['place-orders'])->accessToken; | ||
</syntaxhighlight> | |||
=== فحص النطاقات === | ===فحص النطاقات=== | ||
يتضمن Passport برمجيّتين وسيطتين يمكن استخدامهما للتحقق من أن طلبًا واردًا مصادق عليه برمز مميز تم منحه نطاقًا معينًا. للبدء، أضف الوسيط التالي إلى خاصية $routeMiddleware في ملف | يتضمن Passport برمجيّتين وسيطتين يمكن استخدامهما للتحقق من أن طلبًا واردًا مصادق عليه برمز مميز تم منحه نطاقًا معينًا. للبدء، أضف الوسيط التالي إلى خاصية <code>$routeMiddleware</code> في ملف <code>app/Http/Kernel.php</code>:<syntaxhighlight lang="php"> | ||
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class, | 'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class, | ||
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class, | 'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class, | ||
</syntaxhighlight> | |||
====فحص كل النطاقات==== | |||
قد تعين البرمجيّة الوسيطة <code>scopes</code> لمسار معين للتحقق من أن رمز الوصول الخاص بالطلب الوارد يحتوي على جميع النطاقات المدرجة:<syntaxhighlight lang="php"> | |||
Route::get('/orders', function () { | Route::get('/orders', function () { | ||
// رمز الوصول تحتوي على كلّ من النطاقات “check-status” و “place-orders” ... | |||
// | |||
})->middleware('scopes:check-status,place-orders'); | })->middleware('scopes:check-status,place-orders'); | ||
</syntaxhighlight> | |||
====فحص أيّة نطاقات==== | |||
قد تعين البرمجيّة الوسيطة <code>scopes</code> لمسار معين للتحقق من أن رمز الوصول الخاص بالطلب الوارد يحتوي على الأقل واحدا من النطاقات المدرجة:<syntaxhighlight lang="php"> | |||
Route::get('/orders', function () { | Route::get('/orders', function () { | ||
// رمز الوصول تحتوي على نطاق “check-status” أو “place-orders” ... | // رمز الوصول تحتوي على نطاق “check-status” أو “place-orders” ... | ||
})->middleware('scope:check-status,place-orders'); | })->middleware('scope:check-status,place-orders'); | ||
</syntaxhighlight> | |||
====التحقق من النطاقات على نسخة رمز مُميّز==== | |||
بمجرد دخول طلب مصادق عليه برمز الوصول إلى تطبيقك، قد تستمر في التحقق مما إذا كان الرمز المميز له نطاق معين، باستخدام التابع <code>tokenCan</code> على نسخة مستخدم (User) مصادق عليه:<syntaxhighlight lang="php"> | |||
use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||
سطر 718: | سطر 563: | ||
if ($request->user()->tokenCan('place-orders')) { | if ($request->user()->tokenCan('place-orders')) { | ||
// | |||
} | } | ||
}); | |||
== استخدام واجهة API الخاصة بك مع JavaScript == | </syntaxhighlight> | ||
==استخدام واجهة API الخاصة بك مع JavaScript== | |||
عند إنشاء واجهة َAPI، قد يكون من المفيد جدًّا أن تُستهلك واجهة API الخاصة بك من تطبيق JavaScript خاص بك. يسمح هذا النهج لتطوير واجهة API لتطبيقك بأن يستهلك نفس واجهة API التي تشاركها مع العالم. يمكن استخدام نفس واجهة API من خلال تطبيق الويب الخاص بك، تطبيقات الجوّال، تطبيقات الجهات الخارجية وأية SDK قد تنشرها على مُختلف مديري الحِزَمْ. | عند إنشاء واجهة َAPI، قد يكون من المفيد جدًّا أن تُستهلك واجهة API الخاصة بك من تطبيق JavaScript خاص بك. يسمح هذا النهج لتطوير واجهة API لتطبيقك بأن يستهلك نفس واجهة API التي تشاركها مع العالم. يمكن استخدام نفس واجهة API من خلال تطبيق الويب الخاص بك، تطبيقات الجوّال، تطبيقات الجهات الخارجية وأية SDK قد تنشرها على مُختلف مديري الحِزَمْ. | ||
عادةً، إذا كنت ترغب في استخدام واجهة API الخاصة بك من تطبيق JavaScript، فستحتاج إلى إرسال رمز وصول إلى التطبيق يدويًا وتمريره مع كل طلب إلى التطبيق الخاص بك. ومع ذلك، يتضمن Passport برمجيّة وسيطة يمكنها التعامل مع هذا الأمر نيابةً عنك. كل ما عليك فعله هو إضافة البرمجيّة الوسيطة CreateFreshApiToken إلى مجموعة البرمجيّات الوسيطة web في الملف app/Http/Kernel.php : | عادةً، إذا كنت ترغب في استخدام واجهة API الخاصة بك من تطبيق JavaScript، فستحتاج إلى إرسال رمز وصول إلى التطبيق يدويًا وتمريره مع كل طلب إلى التطبيق الخاص بك. ومع ذلك، يتضمن Passport برمجيّة وسيطة يمكنها التعامل مع هذا الأمر نيابةً عنك. كل ما عليك فعله هو إضافة البرمجيّة الوسيطة <code>CreateFreshApiToken</code> إلى مجموعة البرمجيّات الوسيطة web في الملف <code>app/Http/Kernel.php</code> :<syntaxhighlight lang="php"> | ||
'web' => [ | 'web' => [ | ||
// وسيط آخر ... | // وسيط آخر ... | ||
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, | \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, | ||
], | ], | ||
</syntaxhighlight>سترفق البرمجيّة الوسيطة Passport كعكة <code>laravel_token</code> إلى ردودك الصادرة. تحتوي هذه الكعكة على JWT مشفرة يستخدمها Passport لاستيثاق طلبات واجهة API من تطبيق [[JavaScript]]. الآن، يمكنك تقديم طلبات إلى واجهة API الخاصة بتطبيقك بدون المرور بشكل صريح برمز وصول:<syntaxhighlight lang="php"> | |||
axios.get('/api/user') | axios.get('/api/user') | ||
.then(response => | |||
.then(response => | |||
console.log(response.data); | console.log(response.data); | ||
}); | }); | ||
</syntaxhighlight>عند استخدام طريقة الاستيثاق هذه، فإن سقالات javascript Laravel الافتراضية توجه Axios لإرسال ترويسات X-CSRF-TOKEN و X-Requested-With دائمًا. ومع ذلك، يجب التأكد من تضمين رمز CSRF الخاص بك في العنصر <meta> في HTML:<syntaxhighlight lang="php"> | |||
window.axios.defaults.headers.common = { | window.axios.defaults.headers.common = { | ||
سطر 755: | سطر 596: | ||
}; | }; | ||
</syntaxhighlight>تحذير: إذا كنت تستخدم إطار عمل JavaScript مختلفًا، فيجب عليك التأكد من أنّه مضبوط لإرسال ترويسات X-CSRF-TOKEN و X-Requested-With مع كل طلب صادر. | |||
==الأحداث== | |||
يقوم Passport برفع الأحداث عند إصدار رموز الوصول ورموز للتحديث. يمكنك استخدام هذه الأحداث لتقليم أو إلغاء رموز الوصول الأخرى في قاعدة البيانات الخاصة بك. يمكنك إرفاق المستمعين بهذه الأحداث في <code>EventServiceProvider</code> في التطبيق الخاص بك:<syntaxhighlight lang="php"> | |||
/** | /** | ||
* تعيينات مستمع الحدث الخاصة بالتطبيق. | |||
* | |||
* @متغيير مصفوفة | |||
*/ | |||
protected $listen = [ | protected $listen = [ | ||
'Laravel\Passport\Events\AccessTokenCreated' => [ | 'Laravel\Passport\Events\AccessTokenCreated' => [ | ||
'App\Listeners\RevokeOldTokens', | 'App\Listeners\RevokeOldTokens', | ||
], | ], | ||
'Laravel\Passport\Events\RefreshTokenCreated' => [ | 'Laravel\Passport\Events\RefreshTokenCreated' => [ | ||
'App\Listeners\PruneOldTokens', | 'App\Listeners\PruneOldTokens', | ||
], | ], | ||
]; | ]; | ||
</syntaxhighlight> | |||
==الاختبار== | |||
يمكن استخدام التابع <code>actingAs</code> الخاص بـ Passport لتحديد المستخدم المصادق عليه حاليًا ونطاقاته. الوسيط الأول المعطى للتابع <code>actingAs</code> هو نسخة المستخدم والثاني هو مصفوفة من النطاقات التي يجب منحها إلى رمز المستخدم:<syntaxhighlight lang="php"> | |||
public function testServerCreation() | public function testServerCreation() | ||
{ | { | ||
Passport::actingAs( | Passport::actingAs( | ||
factory(User::class)->create(), | factory(User::class)->create(), | ||
['create-servers'] | ['create-servers'] | ||
); | ); | ||
$response = $this->post('/api/create-server'); | $response = $this->post('/api/create-server'); | ||
$response->assertStatus(200); | $response->assertStatus(200); | ||
} | |||
== مصادر == | </syntaxhighlight> | ||
* صفحة API Authentication (Passport) في توثيق Laravel الرسمي. | ==مصادر== | ||
*[https://laravel.com/docs/5.6/passport صفحة API Authentication (Passport) في توثيق Laravel الرسمي.] | |||
[[تصنيف:Laravel|{{SUBPAGENAME}}]] | |||
[[تصنيف:Laravel Security|{{SUBPAGENAME}}]] |
المراجعة الحالية بتاريخ 06:32، 14 يونيو 2020
مقدمة
يعمل 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);
}