Версія фреймворка: 8.x

Паспорт Laravel

Вступ

Laravel вже дозволяє легко виконувати автентифікацію за допомогою традиційних форм входу, але як щодо API? API зазвичай використовують маркери для автентифікації користувачів і не підтримують стан сеансу між запитами. Laravel робить автентифікацію API легкою, використовуючи Laravel Passport, який забезпечує повну реалізацію сервера OAuth2 для вашого додатку Laravel за лічені хвилини. Паспорт будується поверхСервер OAuth2 лігищо підтримують Енді Міллінгтон і Саймон Хемп.

Ця документація передбачає, що ви вже знайомі з OAuth2. Якщо ви нічого не знаєте про OAuth2, подумайте про ознайомлення із загальнимтермінологіята особливості OAuth2 перед продовженням.

Оновлення паспорта

Під час оновлення до нової основної версії Passport важливо уважно переглянутипосібник з оновлення.

Встановлення

Для початку встановіть Passport через менеджер пакетів Composer:

composer require laravel/passport

Постачальник послуг Passport реєструє власний каталог міграції баз даних із фреймворком, тому вам слід перенести базу даних після встановлення пакету. Міграція Passport створить таблиці, необхідні вашій програмі для зберігання клієнтів та доступу до маркерів:

php artisan migrate

Далі вам слід запуститиpassport:installкоманди. Ця команда створить ключі шифрування, необхідні для створення маркерів безпечного доступу. Крім того, команда створить клієнтів "особистий доступ" та "надання пароля", які будуть використовуватися для генерації маркерів доступу:

php artisan passport:install
Якщо ви хочете використовувати UUID як значення первинного ключа паспортаClientмодель замість автоматичного збільшення цілих чисел, встановіть Passport за допомогоюuuidsваріант.

Після запускуpassport:installдодайте командуLaravel\Passport\HasApiTokensриса до вашогоApp\Models\Userмодель. Ця ознака надасть кілька допоміжних методів для вашої моделі, які дозволять вам перевірити маркер і сфери дії аутентифікованого користувача:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
}

Далі вам слід зателефонувати доPassport::routesметод у межахbootметод вашогоAuthServiceProvider. Цей метод реєструє маршрути, необхідні для видачі маркерів доступу та анулювання маркерів доступу, клієнтів та персональних маркерів доступу:

<?php

namespace App\Providers;

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

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Models\Model' => 'App\Policies\ModelPolicy',
    ];

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

        Passport::routes();
    }
}

Нарешті, у вашомуconfig/auth.phpконфігураційний файл, вам слід встановити файлdriverваріантapiперевірка автентичності доpassport. Це дозволить вашій заявці використовувати паспортTokenGuardпри автентифікації вхідних запитів API:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

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

Клієнтські UUID

Ви можете запуститиpassport:installкоманда за допомогою--uuidsваріант присутній. Цей прапор повідомляє Passport, що ви хочете використовувати UUID замість автоматичного збільшення цілих чисел як PassportClientзначення первинного ключа моделі. Після запускуpassport:installкоманда за допомогою--uuidsВам буде надано додаткові вказівки щодо вимкнення міграції Passport за замовчуванням:

php artisan passport:install --uuids

Розгортання паспорта

Розгортаючи Passport на своїх виробничих серверах вперше, вам, ймовірно, доведеться запуститиpassport:keysкоманди. Ця команда генерує ключі шифрування, необхідні паспорту для генерації маркера доступу. Створені ключі, як правило, не зберігаються в контролі джерела:

php artisan passport:keys

При необхідності ви можете визначити шлях, з якого слід завантажувати ключі Passport. Ви можете використовувати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, який надасть можливість завантажити ключі шифрування зі змінних середовища:

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-----"

Налаштування міграції

Якщо ви не збираєтеся використовувати міграції Passport за замовчуванням, вам слід зателефонувати доPassport::ignoreMigrationsметод уregisterметод вашогоAppServiceProvider. Ви можете експортувати міграції за замовчуванням за допомогоюphp artisan vendor:publish --tag=passport-migrations.

Конфігурація

Клієнтське таємне хешування

Якщо ви хочете, щоб секрети вашого клієнта були хешовані при зберіганні у вашій базі даних, вам слід зателефонувати доPassport::hashClientSecretsметод уbootметод вашогоAppServiceProvider:

Passport::hashClientSecrets();

Після ввімкнення всі ваші секрети клієнта відображатимуться лише один раз, коли ваш клієнт буде створений. Оскільки секретне значення клієнтського текстового тексту ніколи не зберігається в базі даних, відновити його у разі втрати неможливо.

Життєві терміни

За замовчуванням Passport видає довговічні маркери доступу, термін дії яких закінчується через рік. Якщо ви хочете налаштувати довший / коротший термін служби маркера, ви можете використовуватиtokensExpireIn,refreshTokensExpireIn, іpersonalAccessTokensExpireInметоди. Ці методи слід викликати зbootметод вашогоAuthServiceProvider:

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

    Passport::routes();

    Passport::tokensExpireIn(now()->addDays(15));

    Passport::refreshTokensExpireIn(now()->addDays(30));

    Passport::personalAccessTokensExpireIn(now()->addMonths(6));
}
expires_atстовпці таблиць бази даних Passport доступні лише для читання та лише для відображення. Під час випуску токенів Passport зберігає інформацію про термін дії у підписаних та зашифрованих токенах. Якщо вам потрібно визнати маркер недійсним, його слід відкликати.

Заміна стандартних моделей

Ви можете розширити моделі, які використовуються внутрішньо 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);
}

Видача токенів доступу

Використання OAuth2 з кодами авторизації - це те, як більшість розробників знайомі з OAuth2. При використанні кодів авторизації клієнтська програма перенаправляє користувача на ваш сервер, де він або схвалює, або відхиляє запит на видачу клієнту маркера доступу.

Управління клієнтами

По-перше, розробники, що створюють додатки, які повинні взаємодіяти з API вашого додатка, повинні зареєструвати свою програму у вашій, створивши "клієнт". Як правило, це полягає у наданні назви їхньої програми та URL-адреси, на яку ваша програма може переспрямовувати після того, як користувачі затвердять їхній запит на авторизацію.

passport:clientКоманда

Найпростіший спосіб створити клієнта - використанняpassport:clientArtisan командування. Ця команда може бути використана для створення власних клієнтів для тестування функціональності OAuth2. Коли ви запускаєтеclientкоманда, Passport запропонує вам отримати додаткову інформацію про вашого клієнта та надасть ідентифікатор клієнта та секрет:

php artisan passport:client

Переспрямування URL-адрес

Якщо ви хочете дозволити для свого клієнта декілька URL-адрес для переадресації, ви можете вказати їх за допомогою списку, розділеного комами, коли запит на URL-адресуpassport:clientкоманда:

http://example.com/callback,http://examplefoo.com/callback
Будь-яка URL-адреса, яка містить коми, повинна бути закодована.

API JSON

Оскільки ваші користувачі не зможуть використовуватиclientкоманда Passport надає JSON API, який ви можете використовувати для створення клієнтів. Це економить вам проблеми з необхідністю вручну кодувати контролери для створення, оновлення та видалення клієнтів.

Однак вам потрібно буде з'єднати JSON API Passport зі своїм власним інтерфейсом, щоб забезпечити інформаційну панель для ваших користувачів для управління своїми клієнтами. Нижче ми розглянемо всі кінцеві точки API для управління клієнтами. Для зручності ми будемо використовуватиАксіосдля демонстрації надсилання HTTP-запитів до кінцевих точок.

API JSON охороняєтьсяwebіauthMiddlware; тому його можна викликати лише з вашої власної програми. Його не можна викликати із зовнішнього джерела.

GET /oauth/clients

Цей маршрут повертає всіх клієнтів для автентифікованого користувача. Це в першу чергу корисно для переліку всіх клієнтів користувача, щоб вони могли їх редагувати або видаляти:

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

POST /oauth/clients

Цей маршрут використовується для створення нових клієнтів. Для цього потрібні дві частини даних: дані клієнтаnameі aredirectURL.redirectURL-адреса - це те, куди користувач буде перенаправлений після схвалення чи відмови у запиті на авторизацію.

Коли клієнт створюється, йому видається ідентифікатор клієнта та секрет клієнта. Ці значення будуть використовуватися при запиті маркерів доступу з вашої програми. Маршрут створення клієнта поверне новий екземпляр клієнта:

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

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

PUT /oauth/clients/{client-id}

Цей маршрут використовується для оновлення клієнтів. Для цього потрібні дві частини даних: дані клієнтаnameі aredirectURL.redirectURL-адреса - це те, куди користувач буде перенаправлений після схвалення чи відмови у запиті на авторизацію. Маршрут поверне оновлений екземпляр клієнта:

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 (Request $request) {
    $request->session()->put('state', $state = Str::random(40));

    $query = http_build_query([
        'client_id' => 'client-id',
        'redirect_uri' => 'http://example.com/callback',
        'response_type' => 'code',
        'scope' => '',
        'state' => $state,
    ]);

    return redirect('http://your-app.com/oauth/authorize?'.$query);
});
Пам'ятайте,/oauth/authorizeмаршрут вже визначенийPassport::routesметод. Вам не потрібно вручну визначати цей маршрут.

Затвердження запиту

При отриманні запитів на авторизацію Passport автоматично відображає користувачеві шаблон, що дозволяє йому схвалити або відхилити запит на авторизацію. Якщо вони затвердять запит, вони будуть перенаправлені назад доredirect_uriщо було вказано додатком-споживачем.redirect_uriповинен відповідатиredirectURL-адреса, вказана під час створення клієнта.

Якщо ви хочете налаштувати екран затвердження авторизації, ви можете опублікувати подання Passport за допомогоюvendor:publishArtisan командування. Опубліковані погляди будуть розміщені вresources/views/vendor/passport:

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

Іноді вам може знадобитися пропустити запит авторизації, наприклад, під час авторизації власного клієнта. Ви можете досягти цього дорозширенняClientмодельта визначення аskipsAuthorizationметод. ЯкщоskipsAuthorizationповертаєтьсяtrueклієнт буде схвалений, а користувач буде перенаправлений назад доredirect_uriнегайно:

<?php

namespace App\Models\Passport;

use Laravel\Passport\Client as BaseClient;

class Client extends BaseClient
{
    /**
     * Determine if the client should skip the authorization prompt.
     *
     * @return bool
     */
    public function skipsAuthorization()
    {
        return $this->firstParty();
    }
}

Перетворення кодів авторизації для доступу до маркерів

Якщо користувач схвалить запит на авторизацію, він буде перенаправлений назад до програми-споживача. Спочатку споживач повинен перевіритиstateпараметра проти значення, яке зберігалося до перенаправлення. Якщо параметр стану відповідає споживачеві, слід видати aPOSTзапит до вашої програми на запит маркера доступу. Запит повинен містити код авторизації, виданий вашим додатком, коли користувач схвалив запит авторизації. У цьому прикладі ми будемо використовувати бібліотеку Guzzle HTTP для створенняPOSTзапит:

Route::get('/callback', function (Request $request) {
    $state = $request->session()->pull('state');

    throw_unless(
        strlen($state) > 0 && $state === $request->state,
        InvalidArgumentException::class
    );

    $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/tokenroute поверне відповідь JSON, що міститьaccess_token,refresh_token, іexpires_inатрибути.expires_inатрибут містить кількість секунд до закінчення терміну дії маркера доступу.

Подобається/oauth/authorizeмаршрут,/oauth/tokenмаршрут для вас визначенийPassport::routesметод. Не потрібно вручну визначати цей маршрут. За замовчуванням цей маршрут регулюється за допомогою налаштуваньThrottleRequestsMiddlware.

API JSON

Паспорт також включає API JSON для управління авторизованими маркерами доступу. Ви можете поєднати це зі своїм власним інтерфейсом, щоб запропонувати своїм користувачам інформаційну панель для управління маркерами доступу. Для зручності ми будемо використовуватиАксіосдля демонстрації надсилання HTTP-запитів до кінцевих точок. API JSON охороняєтьсяwebіauthMiddlware; тому його можна викликати лише з вашої власної програми.

GET /oauth/tokens

Цей маршрут повертає всі авторизовані маркери доступу, які створив аутентифікований користувач. Це в першу чергу корисно для переліку всіх токенів користувача, щоб вони могли їх відкликати:

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

DELETE /oauth/tokens/{token-id}

Цей маршрут може бути використаний для скасування авторизованих маркерів доступу та пов’язаних з ними маркерів оновлення:

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

Освіжаючі жетони

Якщо ваша програма видає короткочасні маркери доступу, користувачам потрібно буде оновити свої маркери доступу за допомогою маркера оновлення, який був наданий їм під час видачі маркера доступу. У цьому прикладі ми будемо використовувати бібліотеку 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/tokenroute поверне відповідь JSON, що міститьaccess_token,refresh_token, іexpires_inатрибути.expires_inатрибут містить кількість секунд до закінчення терміну дії маркера доступу.

Відкликання жетонів

Ви можете відкликати маркер, використовуючиrevokeAccessTokenметод наTokenRepository. Ви можете відкликати маркери оновлення маркера за допомогоюrevokeRefreshTokensByAccessTokenIdметод наRefreshTokenRepository:

$tokenRepository = app('Laravel\Passport\TokenRepository');
$refreshTokenRepository = app('Laravel\Passport\RefreshTokenRepository');

// Revoke an access token...
$tokenRepository->revokeAccessToken($tokenId);

// Revoke all of the token's refresh tokens...
$refreshTokenRepository->revokeRefreshTokensByAccessTokenId($tokenId);

Очищення токенів

Коли маркери скасовано або закінчився термін їх дії, можливо, ви захочете видалити їх із бази даних. Паспорт поставляється з командою, яка може зробити це за вас:

# Purge revoked and expired tokens and auth codes...
php artisan passport:purge

# Only purge revoked tokens and auth codes...
php artisan passport:purge --revoked

# Only purge expired tokens and auth codes...
php artisan passport:purge --expired

Ви також можете налаштувати aзапланована роботау вашій консоліKernelклас для автоматичного обрізання ваших токенів за розкладом:

/**
 * Define the application's command schedule.
 *
 * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
 * @return void
 */
protected function schedule(Schedule $schedule)
{
    $schedule->command('passport:purge')->hourly();
}

Код дозволу Надання з PKCE

Надання коду авторизації з «Ключем доказу для обміну кодами» (PKCE) - це надійний спосіб автентифікації односторінкових програм або власних програм для доступу до вашого API. Цей грант слід використовувати, коли ви не можете гарантувати, що таємниця клієнта буде зберігатися конфіденційно або для того, щоб зменшити загрозу перехоплення зловмисником коду авторизації. Поєднання "перевірявача коду" та "виклику коду" замінює клієнтський секрет при обміні кодом авторизації на маркер доступу.

Створення клієнта

Перш ніж ваша програма зможе видавати маркери через надання дозволу коду авторизації за допомогою PKCE, вам потрібно буде створити клієнт із підтримкою PKCE. Ви можете зробити це за допомогоюpassport:clientкоманда за допомогою--publicваріант:

php artisan passport:client --public

Запит жетонів

Верифікатор коду та виклик коду

Оскільки цей дозвіл на авторизацію не надає таємницю клієнта, розробникам потрібно буде згенерувати комбінацію перевірителя коду та виклику коду, щоб запросити маркер.

Код, що перевіряє, повинен бути випадковим рядком із 43 до 128 символів, що містить літери, цифри та"-",".","_","~", як визначено вСпецифікація RFC 7636.

Викликом коду має бути кодований рядок Base64 із символами, захищеними URL-адресами та іменами файлів. Відставання'='символи слід видаляти, а розривів рядків, пробілів та інших додаткових символів не повинно бути.

$encoded = base64_encode(hash('sha256', $code_verifier, true));

$codeChallenge = strtr(rtrim($encoded, '='), '+/', '-_');

Перенаправлення на авторизацію

Після створення клієнта ви можете використовувати ідентифікатор клієнта та згенерований код перевірки та виклик коду для запиту коду авторизації та маркера доступу з вашої програми. По-перше, програма-споживач повинна зробити запит на перенаправлення до програми/oauth/authorizeмаршрут:

Route::get('/redirect', function (Request $request) {
    $request->session()->put('state', $state = Str::random(40));

    $request->session()->put('code_verifier', $code_verifier = Str::random(128));

    $codeChallenge = strtr(rtrim(
        base64_encode(hash('sha256', $code_verifier, true))
    , '='), '+/', '-_');

    $query = http_build_query([
        'client_id' => 'client-id',
        'redirect_uri' => 'http://example.com/callback',
        'response_type' => 'code',
        'scope' => '',
        'state' => $state,
        'code_challenge' => $codeChallenge,
        'code_challenge_method' => 'S256',
    ]);

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

Перетворення кодів авторизації для доступу до маркерів

Якщо користувач схвалить запит на авторизацію, він буде перенаправлений назад до програми-споживача. Споживач повинен перевіритиstateпараметра проти значення, яке зберігалося до перенаправлення, як у стандартному наданні коду авторизації.

Якщо параметр стану відповідає, споживач повинен видати aPOSTзапит до вашої програми на запит маркера доступу. Запит повинен містити код авторизації, виданий вашим додатком, коли користувач схвалив запит авторизації, разом із спочатку сформованим засобом перевірки коду:

Route::get('/callback', function (Request $request) {
    $state = $request->session()->pull('state');

    $codeVerifier = $request->session()->pull('code_verifier');

    throw_unless(
        strlen($state) > 0 && $state === $request->state,
        InvalidArgumentException::class
    );

    $response = (new GuzzleHttp\Client)->post('http://your-app.com/oauth/token', [
        'form_params' => [
            'grant_type' => 'authorization_code',
            'client_id' => 'client-id',
            'redirect_uri' => 'http://example.com/callback',
            'code_verifier' => $codeVerifier,
            'code' => $request->code,
        ],
    ]);

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

Токени надання пароля

Надання пароля 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. Цей обсяг може бути призначений лише маркеру, який видається за допомогоюpasswordабоclient_credentialsгрант:

$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' => '*',
    ],
]);

Налаштування постачальника користувачів

Якщо у вашій програмі використовується більше одногоаутентифікація постачальника користувачів, Ви можете вказати, якого постачальника користувачів використовує клієнт, що надає пароль, вказавши a--providerопція при створенні клієнта черезartisan passport:client --passwordкоманди. Вказане ім'я постачальника має відповідати дійсному постачальнику, визначеному у вашомуconfig/auth.phpфайл конфігурації. Тоді можназахистити свій маршрут за допомогою проміжного програмного забезпеченнязабезпечити авторизацію лише користувачів із зазначеного постачальника послуг охорони.

Налаштування поля імені користувача

Під час автентифікації за допомогою надання пароля Passport буде використовуватиemailатрибут вашої моделі як "ім'я користувача". Однак ви можете налаштувати цю поведінку, визначивши afindForPassportметод на вашій моделі:

<?php

namespace App\Models;

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\Models\User
     */
    public function findForPassport($username)
    {
        return $this->where('username', $username)->first();
    }
}

Налаштування перевірки пароля

Під час автентифікації за допомогою надання пароля Passport буде використовуватиpasswordатрибут вашої моделі для перевірки даного пароля. Якщо у вашій моделі немаєpasswordатрибут або ви хочете налаштувати логіку перевірки пароля, ви можете визначити avalidateForPassportPasswordGrantметод на вашій моделі:

<?php

namespace App\Models;

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);
    }
}

Неявні жетони надання

Явне надання подібне до дозволу коду авторизації; однак маркер повертається клієнту без обміну кодом авторизації. Цей грант найчастіше використовується для JavaScript або мобільних додатків, де облікові дані клієнта неможливо надійно зберегти. Щоб увімкнути надання, зателефонуйте наenableImplicitGrantметод у вашомуAuthServiceProvider:

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

    Passport::routes();

    Passport::enableImplicitGrant();
}

Після ввімкнення гранту розробники можуть використовувати свій ідентифікатор клієнта для запиту маркера доступу з вашої програми. Програма-споживач повинна зробити запит на перенаправлення до вашої програми/oauth/authorizeмаршрут так:

Route::get('/redirect', function (Request $request) {
    $request->session()->put('state', $state = Str::random(40));

    $query = http_build_query([
        'client_id' => 'client-id',
        'redirect_uri' => 'http://example.com/callback',
        'response_type' => 'token',
        'scope' => '',
        'state' => $state,
    ]);

    return redirect('http://your-app.com/oauth/authorize?'.$query);
});
Пам'ятайте,/oauth/authorizeмаршрут вже визначенийPassport::routesметод. Вам не потрібно вручну визначати цей маршрут.

Повноваження клієнта надають токени

Надання облікових даних клієнта підходить для автентифікації машини на машину. Наприклад, ви можете використовувати цей грант у запланованому завданні, яке виконує завдання технічного обслуговування через API.

Перш ніж ваша програма зможе видавати токени за допомогою надання клієнтських облікових даних, вам потрібно буде створити клієнтський сертифікат для надання клієнта. Ви можете зробити це за допомогою--clientваріантpassport:clientкоманда:

php artisan passport:client --client

Далі, щоб використовувати цей тип гранту, вам потрібно додатиCheckClientCredentialsMiddlware для$routeMiddlewareвласність вашогоapp/Http/Kernel.phpфайл:

use Laravel\Passport\Http\Middleware\CheckClientCredentials;

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

Потім приєднайте Middlware до маршруту:

Route::get('/orders', function (Request $request) {
    ...
})->middleware('client');

Щоб обмежити доступ до маршруту певними областями, ви можете надати список необхідних областей, розділених комами, при додаванніclientMiddlware до маршруту:

Route::get('/orders', function (Request $request) {
    ...
})->middleware('client:check-status,your-scope');

Отримання жетонів

Щоб отримати маркер за допомогою цього типу надання, зробіть запит до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, або може слугувати більш простим підходом до видачі маркерів доступу загалом.

Створення клієнта персонального доступу

Перш ніж ваша програма зможе видавати маркери особистого доступу, вам потрібно буде створити клієнт персонального доступу. Ви можете зробити це за допомогоюpassport:clientкоманда за допомогою--personalваріант. Якщо ви вже запустилиpassport:installкоманда, вам не потрібно запускати цю команду:

php artisan passport:client --personal

Створивши клієнт вашого особистого доступу, помістіть ідентифікатор клієнта та секретне значення у тексті вашого додатка.envфайл:

PASSPORT_PERSONAL_ACCESS_CLIENT_ID=client-id-value
PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET=unhashed-client-secret-value

Керування токенами особистого доступу

Після створення клієнта особистого доступу ви можете видавати маркери для даного користувача за допомогоюcreateTokenметод наUserекземпляр моделі.createTokenМетод приймає ім'я маркера як перший аргумент та необов'язковий масивсфери діїяк другий аргумент:

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

// Creating a token without scopes...
$token = $user->createToken('Token Name')->accessToken;

// Creating a token with scopes...
$token = $user->createToken('My Token', ['place-orders'])->accessToken;

API JSON

Паспорт також включає JSON API для управління маркерами особистого доступу. Ви можете поєднати це зі своїм власним інтерфейсом, щоб запропонувати своїм користувачам інформаційну панель для управління маркерами особистого доступу. Нижче ми розглянемо всі кінцеві точки API для управління маркерами особистого доступу. Для зручності ми будемо використовуватиАксіосдля демонстрації надсилання HTTP-запитів до кінцевих точок.

API JSON охороняєтьсяwebіauthMiddlware; тому його можна викликати лише з вашої власної програми. Його не можна викликати із зовнішнього джерела.

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

Цей маршрут створює нові маркери особистого доступу. Для цього потрібні дві частини даних: маркерnameтаscopesщо слід призначити маркеру:

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

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

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

Цей маршрут може бути використаний для відкликання жетонів особистого доступу:

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

Захист маршрутів

Через Middleware

Паспорт включаєаутентифікаційний охоронецьщо перевірить маркери доступу на вхідні запити. Після налаштуванняapiохоронець для використанняpassportдрайвера, вам потрібно лише вказатиauth:apiMiddlware на будь-яких маршрутах, які вимагають дійсного маркера доступу:

Route::get('/user', function () {
    //
})->middleware('auth:api');

Кілька захисників автентифікації

Якщо ваша програма автентифікує різні типи користувачів, які, можливо, використовують абсолютно різні моделі Eloquent, вам, ймовірно, доведеться визначити конфігурацію охорони для кожного типу постачальника користувачів у вашій програмі. Це дозволяє захистити запити, призначені для конкретних постачальників користувачів. Наприклад, враховуючи наступну конфігурацію охорониconfig/auth.phpфайл конфігурації:

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

'api-customers' => [
    'driver' => 'passport',
    'provider' => 'customers',
],

Наступний маршрут буде використовуватиapi-customersгвардія, яка використовуєcustomersпостачальника користувачів для автентифікації вхідних запитів:

Route::get('/customer', function () {
    //
})->middleware('auth:api-customers');
Щоб отримати додаткову інформацію про використання кількох постачальників послуг із Passport, зверніться додокументація про надання пароля.

Передача маркера доступу

Під час виклику маршрутів, захищених 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',
]);

Область за замовчуванням

Якщо клієнт не вимагає будь-яких конкретних областей застосування, ви можете налаштувати сервер Passport на приєднання до маркера області за замовчуванням за допомогоюsetDefaultScopeметод. Як правило, вам слід викликати цей метод ізbootметод вашогоAuthServiceProvider:

use Laravel\Passport\Passport;

Passport::setDefaultScope([
    'check-status',
    'place-orders',
]);

Присвоєння сфери дії маркерам

Під час запиту кодів авторизації

Запитуючи маркер доступу з використанням дозволу коду авторизації, споживачі повинні вказати бажаний обсяг якscopeпараметр рядка запиту.scopeпараметром повинен бути розділений пробілом список областей:

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);
});

При видачі токенів особистого доступу

Якщо ви видаєте маркери особистого доступу за допомогоюUserмоделіcreateTokenметоду, ви можете передати масив бажаних областей дії як другий аргумент методу:

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

Перевірка обсягу

Паспорт включає два проміжні програми, які можна використовувати для перевірки автентичності вхідного запиту за допомогою маркера, якому було надано задану область дії. Для початку додайте наступне Middlware до$routeMiddlewareвласність вашогоapp/Http/Kernel.phpфайл:

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

Перевірте всі сфери

scopesMiddlware може бути призначене маршруту для перевірки наявності маркера доступу вхідного запиту_всі_з перелічених областей застосування:

Route::get('/orders', function () {
    // Access token has both "check-status" and "place-orders" scopes...
})->middleware(['auth:api', 'scopes:check-status,place-orders']);

Перевірте будь-які сфери застосування

scopeMiddlware може бути призначене маршруту для перевірки наявності маркера доступу вхідного запиту_принаймні один_з перелічених областей застосування:

Route::get('/orders', function () {
    // Access token has either "check-status" or "place-orders" scope...
})->middleware(['auth:api', 'scope:check-status,place-orders']);

Перевірка обсягу на екземплярі маркера

Після того, як запит автентифікації маркера доступу увійшов у вашу програму, ви все ще можете перевірити, чи має маркер задану область застосування, використовуючиtokenCanметод на аутентифікованомуUserпримірник:

use Illuminate\Http\Request;

Route::get('/orders', function (Request $request) {
    if ($request->user()->tokenCan('place-orders')) {
        //
    }
});

Додаткові методи застосування

scopeIdsметод поверне масив усіх визначених ідентифікаторів / імен:

Laravel\Passport\Passport::scopeIds();

scopesМетод повертає масив усіх визначених областей як екземпляриLaravel\Passport\Scope:

Laravel\Passport\Passport::scopes();

scopesForметод поверне масивLaravel\Passport\Scopeекземпляри, що відповідають заданим ідентифікаторам / іменам:

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

Ви можете визначити, чи визначена дана область застосування, використовуючиhasScopeметод:

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

Споживання вашого API за допомогою JavaScript

Створюючи API, може бути надзвичайно корисно мати можливість використовувати ваш власний API із вашої програми JavaScript. Цей підхід до розробки API дозволяє вашому власному додатку використовувати той самий API, яким ви ділитесь зі світом. Той самий API може використовуватися вашою веб-програмою, мобільними програмами, сторонніми програмами та будь-якими SDK, які ви можете публікувати на різних менеджерах пакетів.

Як правило, якщо ви хочете використовувати ваш API із вашої програми JavaScript, вам доведеться вручну надіслати маркер доступу до програми та передати його з кожним запитом до вашої програми. Однак Passport включає Middlware, яке може це впоратись із вами. Все, що вам потрібно зробити, це додатиCreateFreshApiTokenMiddlware для вашогоwebгрупа проміжного програмного забезпечення у вашомуapp/Http/Kernel.phpфайл:

'web' => [
    // Other middleware...
    \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
Ви повинні переконатися, щоCreateFreshApiTokenMiddlware є останнім проміжним програмним забезпеченням, переліченим у вашому стеку проміжного програмного забезпечення.

До цього проміжного програмного забезпечення Passport буде додано файлlaravel_tokencookie до ваших вихідних відповідей. Цей файл cookie містить зашифрований JWT, який Passport буде використовувати для автентифікації запитів API із вашої програми JavaScript. Термін служби JWT дорівнює вашомуsession.lifetimeзначення конфігурації. Тепер ви можете надсилати запити до API вашого додатка, не передаючи явно маркер доступу:

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

Налаштування назви файлу cookie

Якщо потрібно, ви можете налаштуватиlaravel_tokenім'я файлу cookie з використаннямPassport::cookieметод. Як правило, цей метод слід викликати зbootметод вашогоAuthServiceProvider:

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

    Passport::routes();

    Passport::cookie('custom_name');
}

Захист CSRF

Використовуючи цей метод автентифікації, вам потрібно буде переконатися, що у ваші запити включено дійсний заголовок токена CSRF. Підмостки за замовчуванням JavaScript включають екземпляр Axios, який автоматично використовуватиме зашифрованийXSRF-TOKENзначення файлу cookie для відправкиX-XSRF-TOKENзаголовок на запити того самого походження.

Якщо ви вирішите надіслати файлX-CSRF-TOKENзаголовок замістьX-XSRF-TOKEN, вам потрібно буде використовувати незашифрований маркер, наданийcsrf_token().

Події

Passport викликає події при видачі маркерів доступу та оновлення маркерів. Ви можете використовувати ці події, щоб обрізати або скасувати інші маркери доступу у вашій базі даних. Ви можете приєднати слухачів до цих подій у програмі своєї програмиEventServiceProvider:

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'Laravel\Passport\Events\AccessTokenCreated' => [
        'App\Listeners\RevokeOldTokens',
    ],

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

Тестування

ПаспортactingAsметод може бути використаний для вказівки поточного аутентифікованого користувача, а також його обсягу. Перший аргумент, наданийactingAsметод є екземпляром користувача, а другий - масивом областей, які повинні бути надані маркеру користувача:

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

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

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

    $response->assertStatus(201);
}

ПаспортactingAsClientметод може бути використаний для вказівки поточного аутентифікованого клієнта, а також його обсягу. Перший аргумент, наданийactingAsClientметод є екземпляром клієнта, а другий - масивом областей, які повинні бути надані маркеру клієнта:

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

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

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

    $response->assertStatus(200);
}