سرفصل‌های آموزشی
آموزش OAuth و Laravel Passport
مباحث پیشرفته در Laravel Passport

مباحث پیشرفته در Laravel Passport

به انتهای فصل معرفی Laravel Passport رسیدیم. در این بخش می‌خواهیم مباحث تکمیلی در خصوص Passport را برای شما توضیح دهیم. هر کدام ازقسمت‌های این مقاله، به عنوان مبحث پیشرفته ی موضوعاتی است که در بخش‌های قبلی آموزش داده‌ایم. 

سفارشی سازی Migration

اگر قصد استفاده از Migration های پیش‌فرض پاسپورت را نداشته باشیم، باید متد Passport :: ignoreMigrations را در متد register از کلاسAppServiceProvider  فراخوانی کنیم. ما می‌توانیم migration های پیش‌فرض را export کنیم: 

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

استقرار پاسپورت

هنگامی که برای اولین بار بر روی سرورهای production، پاسپورت را قرار می دهید، باید دستور passport::keys را اجرا کنید. این دستور کلیدهای رمزنگاری‌ای را تولید می‌کند که پاسپورت برای تولید access token نیاز دارد. کلیدهای تولید شده معمولا در source control (منبع کنترل) نگهداری نمی‌شوند:

php artisan passport:keys

در صورت نیاز، می‌توانید مسیری را که کلیدهای پاسپورت باید بارگیری شوند، تعریف کنید. برای این کار از متد Passport::loadKeysFrom استفاده کنید البته دستکاری این تنظیمات توصیه نمی‌شود.

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Passport::routes();

    Passport::loadKeysFrom('/secret-keys/oauth');
}

علاوه بر این شما می‌توانید فایل پیکربندی Passport را با استفاده از دستور زیر منتشر کنید:

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

که در این صورت گزینه بارگیری کلیدهای رمزگذاری از environment variables فراهم می‌شود:

PASSPORT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
<private key here>
-----END RSA PRIVATE KEY-----"

PASSPORT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
<public key here>
-----END PUBLIC KEY-----"

Client Secret Hashing

اگر دوست دارید رمز‌های کلاینت شما در هنگام ذخیره در پایگاه داده به صورت هش باشد، باید متد Passport::hashClientSecrets را در متد boot از کلاس AppServiceProvider فراخوانی کنید. پس از انجام این کار، همه رمز‌های کلاینت شما فقط یک بار در زمان ایجاد کلاینت، ایجاد می‌شود. از آن جا که مقدار رمز کلاینت به صورت plain-text در پایگاه داده ذخیره نمی‌شود، بازیابی آن در صورت گم شدن امکان‌پذیر نیست. 

Passport::hashClientSecrets();

Overriding Default Models

شما می‌توانید مدل‌های داخلی استفاده شده توسط Passport را گسترش دهید:  

use Laravel\Passport\Client as PassportClient;

class Client extends PassportClient
{
    // ...
}

سپس، می‌توانید برای استفاده از مدل‌های سفارشی خود، از طریق کلاس Passport، دستور Passport را بدهید:

use App\Models\Passport\AuthCode;
use App\Models\Passport\Client;
use App\Models\Passport\PersonalAccessClient;
use App\Models\Passport\Token;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Passport::routes();

    Passport::useTokenModel(Token::class);
    Passport::useClientModel(Client::class);
    Passport::useAuthCodeModel(AuthCode::class);
    Passport::usePersonalAccessClientModel(PersonalAccessClient::class);
}

شخصی سازی User Provider

اگر برنامه شما از بیش از یک user provider authentication استفاده می‌کند، می‌توانید با افزودن گزینه --provider در هنگام ایجاد کلاینت از طریق دستور artisan passport:client --password مشخص کنید از کدام user provider استفاده کنید. نام provider داده شده باید با provider معتبر تعریف شده در فایل config/auth.php  مطابقت داشته باشد. سپس می‌توانید مسیر خود را با استفاده از middleware محافظت کنید تا اطمینان حاصل شود که فقط کاربران guard‌ای که provider شما مشخص کرده، احراز هویت می‌شوند. این موضوع در بخش محافظت از مسیر‌ها از طریق middleware در قسمت 14 توضیح داده شده است. 

شخصی سازی فیلد نام کاربری (Username Field)

هنگام تایید اعتبار با استفاده از password grant، پاسپورت از property email مدل user به عنوان نام کاربری یا username استفاده می‌کند. با این وجود، می‌توانید با تعریف یک متد findForPassport در مدل خود این رفتار را شخصی سازی کنید: 

<?php

namespace App;

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

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

    /**
     * Find the user instance for the given username.
     *
     * @param  string  $username
     * @return \App\User
     */
    public function findForPassport($username)
    {
        return $this->where('username', $username)->first();
    }
}

شخصی سازی اعتبار سنجی رمز عبور یا Password validation

هنگام تایید اعتبار با استفاده از password grant، پاسپورت از property password مدل user برای اعتبار سنجی رمز عبور داده شده استفاده می‌کند. اگر مدل شما ویژگی password ندارد یا می‌خواهید منطق اعتبار سنجی رمز عبور را شخصی سازی کنید، می‌توانید یک متد به نام validateForPassportPasswordGrant را در مدل خود تعریف کنید: 

<?php

namespace App;

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

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

    /**
     * Validate the password of the user for the Passport password grant.
     *
     * @param  string  $password
     * @return bool
     */
    public function validateForPassportPasswordGrant($password)
    {
        return Hash::check($password, $this->password);
    }
}

سایر متدهای مربوط به scope   

در مورد Scope ها در قسمت 16 از آموزش، توضیح دادیم. در این بخش، مباحث تکمیلی آن را بیان می‌کنیم.

متد scopeIds یک آرایه‌ای از همه ID‌ها یا نام‌های تعریف شده را برمی گرداند:

Laravel\Passport\Passport::scopeIds();

متد scopes یک آرایه‌ای از همه scope‌های تعریف شده در قالب اشیائی از کلاس Laravel\Passport\Scope بر می‌گرداند.

Laravel\Passport\Passport::scopes();

متد scopesFor آرایه‌ای از اشیا Laravel\Passport\Scope را بر می‌گرداند که با id یا نام‌هایی که به آن دادیم تطابق داشته باشند:

Laravel\Passport\Passport::scopesFor(['place-orders', 'check-status']);

شما می‌توانید با استفاده از متد hasScope تعیین کنید که آیا scope مشخصی تعریف شده است:

Laravel\Passport\Passport::hasScope('place-orders');

Testing

هنگام نوشتن تست، متد actingAs در پاسپورت می‌تواند برای مشخص کردن کاربر معتبر فعلی و scope‌های آن استفاده شود. اولین ورودی متد actingAs یک instance از user است و ورودی دوم یک آرایه‌ای از scope‌هایی است که باید به token کاربر اعطا شود:

use App\User;
use Laravel\Passport\Passport;

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

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

    $response->assertStatus(201);
}

متد actingAsClient در پاسپورت برای مشخص کردن کلاینت فعلی احراز هویت شده و همچنین scope‌های آن استفاده می‌شود. اولین ورودی که به متد actingAsClient داده شده است، به عنوان یک instance کلاینت و آرگومان دوم یک آرایه‌ای از scope‌هایی است که باید به token کلاینت ارائه شود:

use Laravel\Passport\Client;
use Laravel\Passport\Passport;

public function testGetOrders()
{
    Passport::actingAsClient(
        factory(Client::class)->create(),
        ['check-status']
    );

    $response = $this->get('/api/orders');

    $response->assertStatus(200);
}

جمع‌بندی 

در این قسمت به صورت کلی و خلاصه با قابلیت‌هایی از پاسپورت آشنا شدید که دست شما را در شخصی سازی کردن تنظیمات پاسپورت باز گذاشته است. شما می‌توانید بر اساس نیاز پروژه ی خودتان از این قابلیت ها استفاده کنید.

در انتهای فصل آموزش Laravel Passport قرار داریم. امیدواریم که این فصل از دوره ی OAuth2.0 و Laravel Passport برای شما مفید بوده باشد.

لطفا نظرات و سؤالات خودتان را با ما درباره ی این فصل از دوره به اشتراک بگذارید.

online-support-icon