Laravel Passport
Last updated
Was this helpful?
Last updated
Was this helpful?
Laravel уже упрощает выполнение аутентификации с помощью традиционных форм входа, но как насчет API? API обычно используют токены для аутентификации пользователей и не поддерживают состояние сеанса между запросами. Laravel делает аутентификацию API легкой задачей, используя Laravel Passport, который обеспечивает полную реализацию сервера OAuth2 для вашего приложения в течение нескольких минут. Passport построен на , который поддерживается Энди Миллингтоном (Andy Millington) и Саймоном Хэмпом (Simon Hamp).
Эта документация предполагает, что вы уже знакомы с OAuth2. Если вы ничего не знаете об OAuth2, то прежде чем продолжить, ознакомьтесь с общей и особенностями OAuth2.
При обновлении до новой основной версии Passport'а важно внимательно ознакомиться с .
Для начала установите Passport через менеджер пакетов Composer:
Сервис-провайдер Passport регистрирует в фреймворке собственный каталог миграции базы данных, поэтому после установки пакета необходимо выполнить миграцию базы данных. Миграция Passport создаст таблицы, необходимые приложению для хранения клиентов и токенов доступа:
Далее следует запустить команду passport:install
. Эта команда создаст ключи шифрования, необходимые для генерации маркеров безопасного доступа. Кроме того, команда создаст клиентов "персонального доступа (personal access)" и "выдачи пароля (password grant)", которые будут использоваться для генерации токенов доступа:
После выполнения команды passport:install
добавьте трейт Laravel\Passport\HasApiTokens
к вашей модели App\User
. Этот трейт предоставит несколько вспомогательных методов для модели, которые позволят проверять токен аутентифицированного пользователя и области видимости (scopes):
Далее следует вызвать метод Passport::routes
в рамках метода boot
вашего AuthServiceProvider
. В этом методе будут зарегистрированы маршруты, необходимые для выдачи и отзыва токенов доступа, клиентов и персональных токенов доступа:
Наконец, в конфигурационном файле config/auth.php
вы должны установить опцию driver
для защитника api
аутентификации в значение passprot
. Это даст указание приложению использовать TokenGuard
Passport'а при аутентификации входящих API запросов:
Client UUIDs
Вы можете запустить команду passport:install
с опцией --uuids
. Этот флаг укажет Passport'у, что вы хотите использовать UUID вместо автоинкрементирумого целого в качестве значения Primary Key модели Client
. После выполнения команды passport:install
с опцией --uuids
, вам будут даны дополнительные инструкции относительно отключения миграции Passport по умолчанию:
Для публикации Vue-компонентов Passport'а используйте Artisan-команду vendor:publish
:
Опубликованные компоненты будут размещены в каталоге resources/js/components
. После того, как компоненты будут опубликованы, вы должны зарегистрировать их в файле resources/js/app.js
:
После регистрации компонентов, обязательно запустите npm run dev
для перекомпиляции ассетов. После перекомпиляции, Вы можете бросить компоненты в один из шаблонов приложения, чтобы начать создавать клиентов и токены персонального доступа:
При первом развертывании Passport'а на производственных серверах вам, скорее всего, придется выполнить команду passport:keys
. Эта команда генерирует ключи шифрования, необходимые Паспорту для генерации токена доступа. Генерируемые ключи обычно исключаются из системы контроля версий:
При необходимости можно определить путь, откуда будут загружаться ключи паспорта. Для этого можно использовать метод Passport::loadKeysFrom
:
Кроме того, вы можете опубликовать конфигурационный файл паспорта, используя php artisan vendor:published --tag=passport-config
, который затем предоставит возможность загрузить ключи шифрования из переменных окружения:
Если вы не собираетесь использовать миграции Паспорта по умолчанию, вам следует вызвать метод Passport::ignoreMigrations
в методе register
вашего AppServiceProvider
. Вы можете экспортировать миграции по умолчанию, используя php artisan vendor:published --tag=passport-migrations
.
Если вы хотите, чтобы при хранении базе данных токены клиента были хэшированы, вам следует вызвать метод Passport::hashClientSecrets
в методе boot
вашего AppServiceProvider
:
После включения, все ваши клиентские токены будут показаны только один раз, при создании клиента. Так как текстовое значение токена клиента никогда не хранится в базе данных, восстановить его в случае потери невозможно.
По умолчанию паспорт выпускает долговечные токены доступа, срок действия которых истекает через год. Если вы хотите настроить более длительный/короткий срок службы токенов, вы можете использовать методы tokensExpireIn
, refreshTokensExpireIn
и personalAccessTokensExpireIn
. Эти методы должны вызываться из метода boot
вашего AuthServiceProvider
:
Столбцы expires_at
в таблицах базы данных Паспорта предназначены только для чтения и отображения. При выдаче токенов Паспорт хранит информацию об истечении срока действия в подписанных и зашифрованных токенах. Если Вам необходимо сделать токен недействительным, Вы должны его отозвать.
Вы можете свободно расширять модели, используемые внутри паспорта:
Затем, вы можете указать Паспорту, что нужно использовать ваши пользовательские модели через класс Passport
:
Использование OAuth2 с кодами авторизации такое же, как большинство разработчиков знакомы с OAuth2. При использовании кодов авторизации клиентское приложение перенаправит пользователя на ваш сервер, где он либо одобрит, либо отклонит запрос на выдачу токена доступа клиенту.
Сначала разработчикам, создающим приложения, которые должны взаимодействовать с API вашего приложения, нужно будет зарегистрировать свое приложение в вашем, создав "клиент". Обычно это заключается в предоставлении имени своего приложения и URL, на который ваше приложение может быть перенаправлено после того, как пользователи одобрят его запрос на авторизацию.
Команда passport:client
Самый простой способ создания клиента — использование команды passport:client
Artisan. Эта команда может быть использована для создания собственных клиентов для тестирования функциональности OAuth2. При запуске команды client
паспорт запросит у вас дополнительную информацию о вашем клиенте и предоставит вам идентификатор и секрет клиента:
Перенаправление адресов
Если вы хотите разрешить несколько URL-адресов редиректа для вашего клиента, то можете указать их, используя разделенный запятыми список при запросе командой passport:client
URL-адреса:
Любой URL, содержащий запятые, должен быть закодирован.
JSON API
Так как ваши пользователи не смогут использовать команду client
, паспорт предоставляет JSON API, который вы можете использовать для создания клиентов. Это избавляет вас от необходимости вручную писать контроллеры для создания, обновления и удаления клиентов.
JSON API защищен посредниками web
и auth
, поэтому он может быть вызван только из вашего собственного приложения. Он не может быть вызван из внешнего источника.
GET /oauth/clients
Этот маршрут возвращает всех клиентов аутентифицированному пользователю. Это в первую очередь полезно для перечисления всех клиентов пользователя, чтобы он мог их редактировать или удалять:
POST /oauth/clients
Этот маршрут используется для создания новых клиентов. Для него требуются две части данных: имя клиента name
и redirect
— URL для перенаправления. URL-адрес redirect
— это то место, куда пользователь будет перенаправлен после одобрения или отклонения запроса на авторизацию.
При создании клиента ему будет выдан идентификатор и секрет клиента. Эти значения будут использоваться при запросе токенов доступа из вашего приложения. Маршрут создания клиента вернет новый экземпляр клиента:
PUT /oauth/clients/{client-id}
Этот маршрут используется для обновления клиентов. Для него требуются две части данных: имя клиента name
и redirect
— URL для редиректа. URL-адрес redirect
— это то место, куда пользователь будет перенаправлен после одобрения или отклонения запроса на авторизацию. Маршрут вернет обновленный экземпляр клиента:
DELETE /oauth/clients/{client-id}
Этот маршрут используется для удаления клиентов:
Переадресация для авторизации
После создания клиента разработчики могут использовать свой клиентский ID и секрет для запроса кода авторизации и токена доступа из вашего приложения. Сначала запрашивающее приложение должно переадресовать запрос на маршрут /oauth/authorize
вашего приложения таким образом:
Одобрение запроса
При получении запроса на авторизацию Паспорт автоматически выводит пользователю шаблон, позволяющий ему одобрить или отклонить запрос на авторизацию. Если запрос на авторизацию будет одобрен, то он будет перенаправлен обратно на redirect_uri
, который был указан запрашивающим приложением. URL-адрес redirect_uri
должен совпадать с URL-адресом redirect
, который был указан при создании клиента.
Если вы хотите настроить экран одобрения авторизации, то можете опубликовать представления Паспорта, используя команду Artisan vendor:publish
. Опубликованные представления будут размещены в resources/views/vendor/passport
:
Преобразование кодов авторизации в токены доступа
Если пользователь одобрит запрос на авторизацию, то он будет перенаправлен обратно в приложение-потребитель. Потребитель должен сначала проверить параметр state
в сравнении со значением, которое было сохранено до перенаправления. Если параметр "state" соответствует потребителю, то он должен отправить в Ваше приложение запрос "POST" на получение токена доступа. В запросе должен быть указан код авторизации, который был выдан вашим приложением при одобрении запроса на авторизацию пользователем. В данном примере мы будем использовать HTTP-библиотеку Guzzle для создания POST
запроса:
Этот маршрут /oauth/token
вернет JSON-ответ, содержащий атрибуты access_token
, refresh_token
и expires_in
. Атрибут expires_in
содержит количество секунд до истечения срока действия токена доступа.
JSON API
GET /oauth/tokens
Этот маршрут возвращает все токены авторизованного доступа, созданные аутентифицированным пользователем. Это в первую очередь полезно для перечисления всех токенов пользователя, чтобы он мог их отозвать:
DELETE /oauth/tokens/{token-id}
Этот маршрут может использоваться для отзыва токенов авторизованного доступа и связанных с ними токенов обновления:
Если ваше приложение выпускает кратковременные токены доступа, пользователям необходимо будет обновлять свои токены доступа с помощью токена обновления, который был предоставлен им при выпуске токена доступа. В этом примере мы будем использовать HTTP-библиотеку Guzzle для обновления токена:
Этот маршрут /oauth/token
вернет JSON-ответ, содержащий атрибуты access_token
, refresh_token
и expires_in
. Атрибут expires_in
содержит количество секунд до истечения срока действия токена доступа.
Вы можете отозвать токен, используя метод revokeAccessToken
в TokenRepository
. Отзыв токена осуществляется методом revokeRefreshTokensByAccessTokenId
в RefreshTokenRepository
:
Когда маркеры отозваны или просрочены, возможно, вы захотите удалить их из базы данных. Паспорт поставляется с командой, которая может сделать это за вас:
Код авторизации с помощью "Proof Key for Code Exchange" (PKCE) является безопасным способом аутентификации одностраничных приложений или обычных приложений для доступа к вашему API. Этот грант должен использоваться, когда вы не можете гарантировать, что клиентская тайна будет храниться конфиденциально, или для уменьшения угрозы того, что код авторизации будет перехвачен злоумышленником. Комбинация "верификатор кода" и "вызов кода" заменяет клиентский секрет при обмене кода авторизации на токен доступа.
Прежде чем ваше приложение сможет выпускать токены с помощью кода авторизации, выданного с помощью PKCE, вам нужно будет создать клиент с поддержкой PKCE. Вы можете сделать это, используя команду passport:client
с опцией -public
:
Верификатор кода и код вызова
Поскольку данное разрешение на авторизацию не предоставляет секрета клиента, разработчикам необходимо будет сгенерировать комбинацию верификатора кода и вызова кода, чтобы запросить токен.
Кодом вызова должна быть Base64-кодированная строка с URL и символами, безопасными для файлов. Оконечные символы '='
должны быть удалены, и не должно быть ни разрывов строк, ни пробелов, ни других дополнительных символов.
Переадресация для авторизации
После создания клиента вы можете использовать идентификатор клиента и сгенерированный верификатор кода и код вызова для запроса кода авторизации и токена доступа из вашего приложения. Сначала клиентское приложение должно сделать запрос перенаправления на маршрут /oauth/authorize
вашего приложения:
Преобразование кодов авторизации в токены доступа
Если пользователь одобрит запрос на авторизацию, то он будет перенаправлен обратно в клиентское приложение. Оно должено сравнить параметр state
со значением, которое было сохранено до перенаправления, как в стандартном разрешении на код авторизации.
Если параметр состояния совпадает, клиент должен отправить в Ваше приложение POST
запрос на запрос токена доступа. В запросе должен быть указан код авторизации, который был выдан вашим приложением при одобрении запроса на авторизацию пользователем, а также изначально сгенерированный верификатор кода:
The OAuth2 password grant allows your other first-party clients, such as a mobile application, to obtain an access token using an e-mail address / username and password. This allows you to issue access tokens securely to your first-party clients without requiring your users to go through the entire OAuth2 authorization code redirect flow.
Before your application can issue tokens via the password grant, you will need to create a password grant client. You may do this using the passport:client
command with the --password
option. If you have already run the passport:install
command, you do not need to run this command:
Once you have created a password grant client, you may request an access token by issuing a POST
request to the /oauth/token
route with the user's email address and password. Remember, this route is already registered by the Passport::routes
method so there is no need to define it manually. If the request is successful, you will receive an access_token
and refresh_token
in the JSON response from the server:
When using the password grant or client credentials grant, you may wish to authorize the token for all of the scopes supported by your application. You can do this by requesting the *
scope. If you request the *
scope, the can
method on the token instance will always return true
. This scope may only be assigned to a token that is issued using the password
or client_credentials
grant:
When authenticating using the password grant, Passport will use the email
attribute of your model as the "username". However, you may customize this behavior by defining a findForPassport
method on your model:
When authenticating using the password grant, Passport will use the password
attribute of your model to validate the given password. If your model does not have a password
attribute or you wish to customize the password validation logic, you can define a validateForPassportPasswordGrant
method on your model:
The implicit grant is similar to the authorization code grant; however, the token is returned to the client without exchanging an authorization code. This grant is most commonly used for JavaScript or mobile applications where the client credentials can't be securely stored. To enable the grant, call the enableImplicitGrant
method in your AuthServiceProvider
:
Once a grant has been enabled, developers may use their client ID to request an access token from your application. The consuming application should make a redirect request to your application's /oauth/authorize
route like so:
Remember, the
/oauth/authorize
route is already defined by thePassport::routes
method. You do not need to manually define this route.
The client credentials grant is suitable for machine-to-machine authentication. For example, you might use this grant in a scheduled job which is performing maintenance tasks over an API.
Before your application can issue tokens via the client credentials grant, you will need to create a client credentials grant client. You may do this using the --client
option of the passport:client
command:
Next, to use this grant type, you need to add the CheckClientCredentials
middleware to the $routeMiddleware
property of your app/Http/Kernel.php
file:
Then, attach the middleware to a route:
To restrict access to the route to specific scopes you may provide a comma-delimited list of the required scopes when attaching the client
middleware to the route:
To retrieve a token using this grant type, make a request to the oauth/token
endpoint:
Sometimes, your users may want to issue access tokens to themselves without going through the typical authorization code redirect flow. Allowing users to issue tokens to themselves via your application's UI can be useful for allowing users to experiment with your API or may serve as a simpler approach to issuing access tokens in general.
Before your application can issue personal access tokens, you will need to create a personal access client. You may do this using the passport:client
command with the --personal
option. If you have already run the passport:install
command, you do not need to run this command:
After creating your personal access client, place the client's ID and plain-text secret value in your application's .env
file:
Next, you should register these values by placing the following calls to Passport::personalAccessClientId
and Passport::personalAccessClientSecret
within the boot
method of your AuthServiceProvider
:
JSON API
The JSON API is guarded by the web
and auth
middleware; therefore, it may only be called from your own application. It is not able to be called from an external source.
GET /oauth/scopes
GET /oauth/personal-access-tokens
This route returns all of the personal access tokens that the authenticated user has created. This is primarily useful for listing all of the user's tokens so that they may edit or revoke them:
POST /oauth/personal-access-tokens
This route creates new personal access tokens. It requires two pieces of data: the token's name
and the scopes
that should be assigned to the token:
DELETE /oauth/personal-access-tokens/{token-id}
This route may be used to revoke personal access tokens:
Multiple Authentication Guards
If your application authenticates different types of users that perhaps use entirely different Eloquent models, you will likely need to define a guard configuration for each user provider type in your application. This allows you to protect requests intended for specific user providers. For example, given the following guard configuration the config/auth.php
configuration file:
The following route will utilize the api-customers
guard, which uses the customers
user provider, to authenticate incoming requests:
When calling routes that are protected by Passport, your application's API consumers should specify their access token as a Bearer
token in the Authorization
header of their request. For example, when using the Guzzle HTTP library:
Scopes allow your API clients to request a specific set of permissions when requesting authorization to access an account. For example, if you are building an e-commerce application, not all API consumers will need the ability to place orders. Instead, you may allow the consumers to only request authorization to access order shipment statuses. In other words, scopes allow your application's users to limit the actions a third-party application can perform on their behalf.
You may define your API's scopes using the Passport::tokensCan
method in the boot
method of your AuthServiceProvider
. The tokensCan
method accepts an array of scope names and scope descriptions. The scope description may be anything you wish and will be displayed to users on the authorization approval screen:
If a client does not request any specific scopes, you may configure your Passport server to attach a default scope to the token using the setDefaultScope
method. Typically, you should call this method from the boot
method of your AuthServiceProvider
:
When Requesting Authorization Codes
When requesting an access token using the authorization code grant, consumers should specify their desired scopes as the scope
query string parameter. The scope
parameter should be a space-delimited list of scopes:
When Issuing Personal Access Tokens
If you are issuing personal access tokens using the User
model's createToken
method, you may pass the array of desired scopes as the second argument to the method:
Passport includes two middleware that may be used to verify that an incoming request is authenticated with a token that has been granted a given scope. To get started, add the following middleware to the $routeMiddleware
property of your app/Http/Kernel.php
file:
Check For All Scopes
The scopes
middleware may be assigned to a route to verify that the incoming request's access token has all of the listed scopes:
Check For Any Scopes
The scope
middleware may be assigned to a route to verify that the incoming request's access token has at least one of the listed scopes:
Checking Scopes On A Token Instance
Once an access token authenticated request has entered your application, you may still check if the token has a given scope using the tokenCan
method on the authenticated User
instance:
Additional Scope Methods
The scopeIds
method will return an array of all defined IDs / names:
The scopes
method will return an array of all defined scopes as instances of Laravel\Passport\Scope
:
The scopesFor
method will return an array of Laravel\Passport\Scope
instances matching the given IDs / names:
You may determine if a given scope has been defined using the hasScope
method:
When building an API, it can be extremely useful to be able to consume your own API from your JavaScript application. This approach to API development allows your own application to consume the same API that you are sharing with the world. The same API may be consumed by your web application, mobile applications, third-party applications, and any SDKs that you may publish on various package managers.
Typically, if you want to consume your API from your JavaScript application, you would need to manually send an access token to the application and pass it with each request to your application. However, Passport includes a middleware that can handle this for you. All you need to do is add the CreateFreshApiToken
middleware to your web
middleware group in your app/Http/Kernel.php
file:
You should ensure that the
CreateFreshApiToken
middleware is the last middleware listed in your middleware stack.
This Passport middleware will attach a laravel_token
cookie to your outgoing responses. This cookie contains an encrypted JWT that Passport will use to authenticate API requests from your JavaScript application. The JWT has a lifetime equal to your session.lifetime
configuration value. Now, you may make requests to your application's API without explicitly passing an access token:
Customizing The Cookie Name
If needed, you can customize the laravel_token
cookie's name using the Passport::cookie
method. Typically, this method should be called from the boot
method of your AuthServiceProvider
:
CSRF Protection
When using this method of authentication, you will need to ensure a valid CSRF token header is included in your requests. The default Laravel JavaScript scaffolding includes an Axios instance, which will automatically use the encrypted XSRF-TOKEN
cookie value to send a X-XSRF-TOKEN
header on same-origin requests.
If you choose to send the
X-CSRF-TOKEN
header instead ofX-XSRF-TOKEN
, you will need to use the unencrypted token provided bycsrf_token()
.
Passport raises events when issuing access tokens and refresh tokens. You may use these events to prune or revoke other access tokens in your database. You may attach listeners to these events in your application's EventServiceProvider
:
Passport's actingAs
method may be used to specify the currently authenticated user as well as its scopes. The first argument given to the actingAs
method is the user instance and the second is an array of scopes that should be granted to the user's token:
Passport's actingAsClient
method may be used to specify the currently authenticated client as well as its scopes. The first argument given to the actingAsClient
method is the client instance and the second is an array of scopes that should be granted to the client's token:
Для того, чтобы использовать Vue-компоненты Passport'а, необходим javascript-фреймворк . Эти компоненты также используют фреймворк Bootstrap CSS. Однако, даже если вы не используете данные инструменты, эти компоненты служат ценным справочником для вашей собственной реализации фронтенда.
До версии Laravel v5.7.19 добавление по умолчанию
при регистрации компонентов приводит к консольной ошибке. Объяснение этого изменения можно найти в .
Тем не менее, вам нужно будет сопоставить JSON API паспорта с вашим собственным фронтэндом, чтобы обеспечить панель инструментов для ваших пользователей для управления своими клиентами. Ниже мы рассмотрим все конечные точки API для управления клиентами. Для удобства мы используем , чтобы продемонстрировать выполнение HTTP-запросов к конечным точкам.
Если Вы не хотите самостоятельно реализовывать весь фронтенд управления клиентами, Вы можете использовать , чтобы иметь полнофункциональный фронтенд в считанные минуты.
Иногда вам может понадобиться пропустить запрос авторизации, например, при авторизации клиента первой стороны. Вы можете сделать это, и определив метод skipsAuthorization
. Если skipsAuthorization
вернёт true
, то клиент будет одобрен и пользователь будет немедленно перенаправлен обратно в redirect_uri
:
Паспорт также включает JSON API для управления токенами авторизованного доступа. Вы можете связать его с вашим собственным фронтендом, чтобы предложить вашим пользователям панель инструментов для управления токенами доступа. Для удобства мы используем , чтобы продемонстрировать выполнение HTTP-запросов к конечным точкам. JSON API защищен посредниками web
и auth
, поэтому он может быть вызван только из вашего собственного приложения.
Вы также можете настроить в классе Kernel
вашей консоли, чтобы автоматически удалять токены по расписанию:
Верификатор кода должен представлять собой случайную строку от 43 до 128 символов, содержащую буквы, цифры и "-"
, "."
, "_"
, "~"
, как определено в .
Remember, access tokens are long-lived by default. However, you are free to if needed.
If your application uses more than one , you may specify which user provider the password grant client uses by providing a --provider
option when creating the client via the artisan passport:client --password
command. The given provider name should match a valid provider defined in your config/auth.php
configuration file. You can then to ensure that only users from the guard's specified provider are authorized.
Once you have created a personal access client, you may issue tokens for a given user using the createToken
method on the User
model instance. The createToken
method accepts the name of the token as its first argument and an optional array of as its second argument:
Passport also includes a JSON API for managing personal access tokens. You may pair this with your own frontend to offer your users a dashboard for managing personal access tokens. Below, we'll review all of the API endpoints for managing personal access tokens. For convenience, we'll use to demonstrate making HTTP requests to the endpoints.
If you don't want to implement the personal access token frontend yourself, you can use the to have a fully functional frontend in a matter of minutes.
This route returns all of the defined for your application. You may use this route to list the scopes a user may assign to a personal access token:
Passport includes an that will validate access tokens on incoming requests. Once you have configured the api
guard to use the passport
driver, you only need to specify the auth:api
middleware on any routes that require a valid access token:
For more information on using multiple user providers with Passport, please consult the .