Мульти аутентификация с Laravel 5.4 и паспортом

Я пытаюсь настроить multi auth с Laravel Passport, но, похоже, это не поддерживается. Я использую Предоставление пароля для выдачи токенов, что требует от меня ввода имени пользователя / пароля пользователя, которому нужны токены доступа.

У меня есть 3 установщика аутентификации / провайдера, всего 4.
Пользователи, поставщики, администраторы и API

2 из Auths должны иметь паспортный доступ, поэтому каждый пользователь должен иметь возможность выдавать токены. Но Passport автоматически принимает провайдера аутентификации API, но я хочу, чтобы это изменилось в зависимости от того, какой пользователь входит в систему. Если пользователь делает, то Пользователь провайдер и если его поставщик, то Поставщик поставщика.

Но способ, которым Passport в настоящее время поддерживает только 1 тип пользователя, поэтому по умолчанию API провайдер.

Есть ли что-то лучшее для этого? или я должен пойти с аутентификацией на основе ролей вместо этого.

4

Решение

Если вам все еще нужно.

Я предпочитаю идти с ролями, для этого есть замечательный плагин: https://github.com/larapacks/authorization

Но если вам это как-то нужно, вы сможете использовать следующие шаги.

Для нескольких охранников вам придется перезаписать некоторый код.

Вместо загрузки PassportServiceProvider вы создаете свой собственный, расширяете PassportServiceProvider и перезаписываете метод makePasswordGrant.
В этом методе вы измените пользовательский репозиторий Passport для своего собственного расширенного репозитория. В пользовательском репозитории вы должны изменить конфигурацию статической модели на динамическую (я загружаю из атрибутов запроса, но вы можете получить откуда угодно).

Возможно, вам придется переписать что-то еще, но я сделал тест и работает.

Пример:

PassportServiceProvider

namespace App\Providers;

use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Grant\PasswordGrant;
use Laravel\Passport\PassportServiceProvider as BasePassportServiceProvider;
use Laravel\Passport\Passport;

class PassportServiceProvider extends BasePassportServiceProvider
{
/**
* Create and configure a Password grant instance.
*
* @return PasswordGrant
*/
protected function makePasswordGrant()
{
$grant = new PasswordGrant(
$this->app->make(\App\Repositories\PassportUserRepository::class),
$this->app->make(\Laravel\Passport\Bridge\RefreshTokenRepository::class)
);

$grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());

return $grant;
}

}

UserRepository

namespace App\Repositories;

use App;
use Illuminate\Http\Request;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use Laravel\Passport\Bridge\UserRepository;
use Laravel\Passport\Bridge\User;
use RuntimeException;

class PassportUserRepository extends UserRepository
{
/**
* {@inheritdoc}
*/
public function getUserEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity)
{
$guard = App::make(Request::class)->attributes->get('guard') ?: 'api';
$provider = config("auth.guards.{$guard}.provider");if (is_null($model = config("auth.providers.{$provider}.model"))) {
throw new RuntimeException('Unable to determine user model from configuration.');
}if (method_exists($model, 'findForPassport')) {
$user = (new $model)->findForPassport($username);
} else {
$user = (new $model)->where('email', $username)->first();
}if (! $user ) {
return;
} elseif (method_exists($user, 'validateForPassportPasswordGrant')) {
if (! $user->validateForPassportPasswordGrant($password)) {
return;
}
} elseif (! $this->hasher->check($password, $user->password)) {
return;
}

return new User($user->getAuthIdentifier());
}
}

PS: Извините, мой плохой английский.

5

Другие решения

Вы должны изменить основную библиотеку файлов.

1) Файл: vendor \ laravel \ passport \ src \ Bridge \ UserRepository.php

найти getUserEntityByUserCredentials и скопируйте полный метод и вставьте этот метод ниже с именем getEntityByUserCredentials. Не изменяйте основную функцию, потому что она где-то используется.

//Add the $provider variable at last or replace this line.
public function getEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity, $provider)

Затем в новой дублированной функции найдите следующее:

$provider = config('auth.guards.api.provider');

и заменить его на:

$provider = config('auth.guards.'.$provider.'.provider');

2) Файл: vendor \ league \ oauth2-server \ src \ Grant \ PasswordGrant.php

В функции ValidateUser добавьте следующий код после строки №. 88

$provider = $this->getRequestParameter('provider', $request);

if (is_null($provider)) {
throw OAuthServerException::invalidRequest('provider');
}

После добавления замените следующий код на

$user = $this->userRepository->getEntityByUserCredentials(
$username,
$password,
$this->getIdentifier(),
$client,
$provider
);

Теперь попробуйте это с помощью почтальона

Добавьте поле провайдера в поле ввода как

provider = api_vendors
OR
provider = api_admins
OR
provider = api_users
And so on....

убедитесь, что вы добавили своего провайдера и задали драйверы в config / auth.php

'guards' => [
'api_admins' => [
'driver' => 'passport',
'provider' => 'admins',
],
'api_vendors' => [
'driver' => 'passport',
'provider' => 'vendors',
],

Надеюсь, это поможет.

3

Я создал небольшой пакет для этой проблемы. Вот ссылка на полный документ ссылка на сайт

Но суть в том, что всякий раз, когда user субъект авторизуется, проверяет охранников и провайдеров.

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

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

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

'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => 'App\User',
],
/**
* This is the important part. You can create as many providers as you like but right now,
* we just need the customer
*/
'customers' => [
'driver' => 'eloquent',
'model' => 'App\Customer',
],
],

У вас должен быть такой контроллер:

<?php

namespace App\Http\Controllers\Auth;

use App\Customers\Customer;
use App\Customers\Exceptions\CustomerNotFoundException;
use Illuminate\Database\ModelNotFoundException;
use Laravel\Passport\Http\Controllers\AccessTokenController;
use Laravel\Passport\TokenRepository;
use League\OAuth2\Server\AuthorizationServer;
use Psr\Http\Message\ServerRequestInterface;
use Lcobucci\JWT\Parser as JwtParser;

class CustomerTokenAuthController extends AccessTokenController
{
/**
* The authorization server.
*
* @var \League\OAuth2\Server\AuthorizationServer
*/
protected $server;

/**
* The token repository instance.
*
* @var \Laravel\Passport\TokenRepository
*/
protected $tokens;

/**
* The JWT parser instance.
*
* @var \Lcobucci\JWT\Parser
*/
protected $jwt;

/**
* Create a new controller instance.
*
* @param  \League\OAuth2\Server\AuthorizationServer  $server
* @param  \Laravel\Passport\TokenRepository  $tokens
* @param  \Lcobucci\JWT\Parser  $jwt
*/
public function __construct(AuthorizationServer $server,
TokenRepository $tokens,
JwtParser $jwt)
{
parent::__construct($server, $tokens, $jwt);
}

/**
* Override the default Laravel Passport token generation
*
* @param ServerRequestInterface $request
* @return array
* @throws UserNotFoundException
*/
public function issueToken(ServerRequestInterface $request)
{
$body = (parent::issueToken($request))->getBody()->__toString();
$token = json_decode($body, true);

if (array_key_exists('error', $token)) {
return response()->json([
'error' => $token['error'],
'status_code' => 401
], 401);
}

$data = $request->getParsedBody();

$email = $data['username'];

switch ($data['provider']) {
case 'customers';

try {

$user = Customer::where('email', $email)->firstOrFail();

} catch (ModelNotFoundException $e) {
return response()->json([
'error' => $e->getMessage(),
'status_code' => 401
], 401);
}

break;

default :

try {

$user = User::where('email', $email)->firstOrFail();

} catch (ModelNotFoundException $e) {
return response()->json([
'error' => $e->getMessage(),
'status_code' => 401
], 401);
}
}

return compact('token', 'user');
}
}

и запрос должен быть:

POST /api/oauth/token HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache

grant_type=password&username=test%40email.com&password=secret&provider=customers

Чтобы проверить ваш контроллер, который является вошедшим в систему пользователем, вы можете сделать:

auth()->guard('customers')->user()

1

Мы ожидаем, что Laravel добавит эту функцию в свой пакет, но для тех, кто хочет добавить эту функцию, я предлагаю использовать этот пакет

1

Паспорт Laravel работает только с Пользователем в качестве провайдера. Даже если вы получите токен, добавив вышеуказанные изменения с PasswordGrant & UserRepository, пока вы обращаетесь к API, вызываете Post и получаете запросы, не работающие с измененным поставщиком паспортов, кроме User.

Лучше создать мульти-аутентификацию с драйвером сеанса, если это необходимо для поставщиков и клиентов. пусть модель «Пользователь» используется только для паспорта, столбцы таблицы которого поддерживают admin, API, vendor и т. д.

Репо здесь Laravel-multiAuth

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector