Настройка ответа на токен Laravel Passport
В настоящий момент я работаю над API и попал в кирпичную стену. Я использую Passport с типом типа "Пароль".
Я хочу вернуть информацию пользователя с помощью токенов доступа, однако я не уверен, как это сделать.
Какой класс я могу реализовать, отредактировать или расширить, чтобы получить это?
Я бы хотел, чтобы это было возвращено:
{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "lalalalalal",
"refresh_token": "lalalallala",
"user": {
"username": "a username",
"user_type": "admin"
}
}
Спасибо заранее.
Ответы
Ответ 1
Инструкции о том, как это сделать, описаны в классе BearerTokenResponse
(входит в пакет league/oauth2-server).
Проверено на Laravel 5.7.
1. Расширьте класс BearerTokenResponse
, добавьте в ответ дополнительные параметры, которые вам нужны.
namespace App\Auth;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
class BearerTokenResponse extends \League\OAuth2\Server\ResponseTypes\BearerTokenResponse
{
/**
* Add custom fields to your Bearer Token response here, then override
* AuthorizationServer::getResponseType() to pull in your version of
* this class rather than the default.
*
* @param AccessTokenEntityInterface $accessToken
*
* @return array
*/
protected function getExtraParams(AccessTokenEntityInterface $accessToken): array
{
return [
'user_id' => $this->accessToken->getUserIdentifier(),
];
}
}
2. Создайте свой собственный класс PassportServiceProvider
и переопределите метод makeAuthorizationServer()
, чтобы передать свой собственный класс BearerTokenResponse
.
namespace App\Providers;
use App\Auth\BearerTokenResponse;
use Laravel\Passport\Bridge;
use League\OAuth2\Server\AuthorizationServer;
class PassportServiceProvider extends \Laravel\Passport\PassportServiceProvider
{
/**
* Make the authorization service instance.
*
* @return \League\OAuth2\Server\AuthorizationServer
*/
public function makeAuthorizationServer()
{
return new AuthorizationServer(
$this->app->make(Bridge\ClientRepository::class),
$this->app->make(Bridge\AccessTokenRepository::class),
$this->app->make(Bridge\ScopeRepository::class),
$this->makeCryptKey('private'),
app('encrypter')->getKey(),
new BearerTokenResponse() // <-- The class you created above
);
}
}
3. Добавьте вашего провайдера в массив провайдеров в config/app.php
/*
* Application Service Providers...
*/
App\Providers\PassportServiceProvider::class,
4. Исключите паспортный пакет из автоматического обнаружения laravel в composer.json
Это останавливает загрузку класса PassportServiceProvider
по умолчанию.
"extra": {
"laravel": {
"dont-discover": [
"laravel/passport"
]
}
},
Затем запустите composer install
.
Ответ 2
Еще один лучший ответ из Интернета
Пользовательский Laravel Passport BearerTokenResponse
https://gist.github.com/messi89/489473c053e3ea8d9e034b0032effb1d
Ответ 3
Два шага.
1. Добавить новый маршрут в файл маршрутов.
// routes/api.php
Route::post('oauth/token', '[email protected]');
Помните, что это изменит маршрут для получения токена от /oauth/token
до /api/oauth/token
.
2. Добавить метод контроллера.
<?php
// app/Http/Controllers/AuthController.php
namespace App\Http\Controllers;
use App\User;
use Psr\Http\Message\ServerRequestInterface;
use \Laravel\Passport\Http\Controllers\AccessTokenController;
class AuthController extends AccessTokenController
{
public function auth(ServerRequestInterface $request)
{
$tokenResponse = parent::issueToken($request);
$token = $tokenResponse->getContent();
// $tokenInfo will contain the usual Laravel Passort token response.
$tokenInfo = json_decode($token, true);
// Then we just add the user to the response before returning it.
$username = $request->getParsedBody()['username'];
$user = User::whereEmail($username)->first();
$tokenInfo = collect($tokenInfo);
$tokenInfo->put('user', $user);
return $tokenInfo;
}
}
Ответ 4
Я использую Multi-Auth с паспортом, поэтому предыдущие ответы мне не помогли.
После нескольких часов "поиска в Google" я нашел этот ответ (after-) middleware.
Мое промежуточное программное обеспечение в основном получает результат проверки подлинности Passport, проверяет, есть ли внутри Bearer, и добавляет дополнительные данные к содержимому.
<?php
namespace App\Http\Middleware;
use Closure;
class AppendTokenResponse
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$content = json_decode($response->content(), true);
if (!empty($content['access_token'])) {
$content['moredata'] = 'some data';
$response->setContent($content);
}
return $response;
}
}
Теперь поместите новое промежуточное ПО в $ routemiddleware в App/Http/Kernel.php
/**
* The application route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'cors' => \App\Http\Middleware\Cors::class,
'multiauth' => \SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'oauth.providers' => \SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class,
'append_auth' =>\App\Http\Middleware\AppendTokenResponse::class,
];
Затем просто зарегистрируйте это промежуточное ПО для паспортных маршрутов в Providers/AuthServiceProvider.php
С MultiAuth:
Route::group(['middleware' => ['oauth.providers','append_auth']], function () {
Passport::routes(function ($router) {
return $router->forAccessTokens();
});
});
Я считаю, что обычный паспорт должен быть (не проверен):
Route::group(['middleware' => ['append_auth']], function () {
Passport::routes();
});
Ответ 5
Вы можете легко это сделать. Откройте файл BearerTokenResponse.php
расположенный в vendor\league\oauth2-server\src\ResponseTypes
Измените метод generateHttpResponse (ResponseInterface $response) следующим образом:
public function generateHttpResponse(ResponseInterface $response)
{
$expireDateTime = $this->accessToken->getExpiryDateTime()->getTimestamp();
$jwtAccessToken = $this->accessToken->convertToJWT($this->privateKey);
$responseParams = [
'token_type' => 'Bearer',
'expires_in' => $expireDateTime - (new \DateTime())->getTimestamp(),
'access_token' => (string) $jwtAccessToken,
'user' => User::find($this->accessToken->getUserIdentifier()),
];
if ($this->refreshToken instanceof RefreshTokenEntityInterface) {
$refreshToken = $this->encrypt(
json_encode(
[
'client_id' => $this->accessToken->getClient()->getIdentifier(),
'refresh_token_id' => $this->refreshToken->getIdentifier(),
'access_token_id' => $this->accessToken->getIdentifier(),
'scopes' => $this->accessToken->getScopes(),
'user_id' => $this->accessToken->getUserIdentifier(),
'expire_time' => $this->refreshToken->getExpiryDateTime()->getTimestamp(),
]
)
);
$responseParams['refresh_token'] = $refreshToken;
}
$responseParams = array_merge($this->getExtraParams($this->accessToken), $responseParams);
$response = $response
->withStatus(200)
->withHeader('pragma', 'no-cache')
->withHeader('cache-control', 'no-store')
->withHeader('content-type', 'application/json; charset=UTF-8');
$response->getBody()->write(json_encode($responseParams));
return $response;
}
Не забудьте использовать модель App\User.
Надеюсь, это поможет вам.