Multi Auth with Laravel 5.4 and passport

I am trying to configure multi auth using Laravel Passport, but it does not seem to support it. I use Password Grant to issue tokens that require me to pass the username / password of the user who wants access tokens.

I have 3 auth guard / providers installations, total 4. Users, sellers, admins and APIs

2 Auths requires access to a passport, so every user should be able to issue tokens. But Passport automatically accepts the API provider of the APIs, but I want this to change depending on which user logs on. If the user does this, then the user’s provider and if his supplier then the supplier’s supplier.

But the way Passport currently only supports one user type, so its the default for the API provider.

Is there anything better for this? or should I use role-based authentication.

+4
source share
4 answers

If you still need to.

I prefer to work with roles, there is an amazing plugin for this: https://github.com/larapacks/authorization

But if you need this for some reason, you can use the following steps below.

For several guards, you will have to rewrite some code.

, PassportServiceProvider, PassportServiceProvider makePasswordGrant. Passport UserRepository . ( , ).

, - , .

:

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: , .

+4

.

1) : vendor\laravel\passport\src\Bridge\UserRepository.php

getUserEntityByUserCredentials getEntityByUserCredentials. Donot , -.

//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 no. 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 . , PasswordGrant UserRepository, API , , .

You'd better create multi auth using the session driver, if necessary for suppliers and customers. let the User model be only for a passport whose table columns support the administrator, API, provider, etc.

Repo here laravel-multiAuth

0
source

Source: https://habr.com/ru/post/1670245/


All Articles