Laravel Passport Multiple Authentication using Guards

前端 未结 4 514
说谎
说谎 2020-12-09 06:54

Can we use laravel passport with different guards to authenticate APIs for two different types of users. For example we have driver app for driver user and vendor app for ve

相关标签:
4条回答
  • 2020-12-09 07:00

    You don't necessarily need to change config for each request. You need a client for each guard. After creating clients by running

    passport:install
    

    Make sure you specified provider field in database. It should be same value as auth.providers config.

    After creating clients and guards, use following code when creating an access token.

    App::clearResolvedInstance(ClientRepository::class);
    app()->singleton(ClientRepository::class, function () {
        return new ClientRepository(User::CLIENT_ID, null); // Client id of the model
    });
    

    Make sure you specified provider in oauth_clients table.

    0 讨论(0)
  • 2020-12-09 07:01

    I managed to create multiple auths (with laravel/passport) by using a simple middlware.

    Step 1: config/auth.php

    Add your user classes to providers

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
    
        'api' => [
            'driver' => 'passport',
            'provider' => 'basic_users', // default
        ],        
    ],
    
    ...
    
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'admin_users' => [
            'driver' => 'eloquent',
            'model' => App\AdminUser::class,
        ],
        'basic_users' => [
            'driver' => 'eloquent',
            'model' => App\BasicUser::class,
        ],
    ],
    

    Clean the cache via CLI

    php artisan config:cache
    

    Step 2: Create middleware

    php artisan make:middleware AdminUserProvider
    

    Open the newly created middleware in app/Http/Middleware and update the hand method like below

    public function handle($request, Closure $next)
    {
        config(['auth.guards.api.provider' => 'admin_users']);
        return $next($request);
    }
    

    Step 3: Register your middleware

    Add the newly created middleware to $routeMiddleware

    protected $routeMiddleware = [
        ...
        'auth.admin' => \App\Http\Middleware\AdminUserProvider::class,
    ];
    

    and make sure it's at the top of $middlewarePriority

    protected $middlewarePriority = [
        \App\Http\Middleware\AdminUserProvider::class,
        ...
    ];
    

    Step 4: Add middleware to route

    Route::group(['middleware' => ['auth.admin','auth:api']], function() {
    

    Step 5: LoginControllers (AdminUserController & BasicUserController)

    public function login()
    {
        $validatedData = request()->validate([
            'email' => 'required',
            'password' => 'required|min:6'
        ]);
        // get user object
        $user = AdminUser::where('email', request()->email)->first();
        // do the passwords match?
        if (!Hash::check(request()->password, $user->password)) {
            // no they don't
            return response()->json(['error' => 'Unauthorized'], 401);
        }
        // log the user in (needed for future requests)
        Auth::login($user);
        // get new token
        $tokenResult = $user->createToken($this->tokenName);
        // return token in json response
        return response()->json(['success' => ['token' => $tokenResult->accessToken]], 200);
    }
    

    In summary:

    The login controllers use Eloquent models to get the user object and then log the user in through Auth::login($user)

    Then for future requests that need authentication, the new middleware will change the api auth guard provider to the correct class.

    0 讨论(0)
  • 2020-12-09 07:08

    After spent time I have found that in Laravel 7 there is no custom code required except some configuration. For details please check this answer I have tested & implemented in my projects Multi Auth with Laravel 5.4 and Passport

    0 讨论(0)
  • 2020-12-09 07:15

    Here is an example of auth.php and api.php to start with

    config/auth.php

    <?php
    
    return [
    
        /*
        |--------------------------------------------------------------------------
        | Authentication Defaults
        |--------------------------------------------------------------------------
        */
    
        'defaults' => [
            'guard' => 'web',
            'passwords' => 'users',
        ],
    
        /*
        |--------------------------------------------------------------------------
        | Authentication Guards
        |--------------------------------------------------------------------------
        */
    
        'guards' => [
    
            'web' => [
                'driver' => 'session',
                'provider' => 'users',
            ],
    
            'driver-api' => [
                'driver' => 'passport',
                'provider' => 'drivers',
            ],
    
            'vendor-api' => [
                'driver' => 'passport',
                'provider' => 'vendors',
            ],
        ],
    
        /*
        |--------------------------------------------------------------------------
        | User Providers
        |--------------------------------------------------------------------------
        */
    
        'providers' => [
    
            'users' => [
                'driver' => 'eloquent',
                'model' => App\User::class,
            ],
    
            'drivers' => [
                'driver' => 'eloquent',
                'model' => App\Driver::class,
            ],
    
            'vendors' => [
                'driver' => 'eloquent',
                'model' => App\Vendor::class,
            ],
        ],
    
        /*
        |--------------------------------------------------------------------------
        | Resetting Passwords
        |--------------------------------------------------------------------------
        */
    
        'passwords' => [
    
            'users' => [
                'provider' => 'users',
                'table' => 'password_resets',
                'expire' => 60,
            ],
    
            'drivers' => [
                'provider' => 'drivers',
                'table' => 'password_resets',
                'expire' => 60,
            ],
    
            'vendors' => [
                'provider' => 'vendors',
                'table' => 'password_resets',
                'expire' => 60,
            ],
        ],
    
    ];
    

    routes/api.php

    <?php
    
    use Illuminate\Http\Request;
    
    /*
    |--------------------------------------------------------------------------
    | API Routes
    |--------------------------------------------------------------------------
    */
    
    Route::group(['namespace' => 'Driver', 'prefix' => 'driver/v1', 'middleware' => 'auth:driver-api'], function() {
    
        // define your routes here for the "drivers"
    });
    
    Route::group(['namespace' => 'Vendor', 'prefix' => 'vendor/v1', 'middleware' => 'auth:vendor-api'], function() {
    
        // define your routes here for the "vendors"
    });
    

    You have to modify this files:

    File: vendor\laravel\passport\src\Bridge\UserRepository.php

    Copy/Paste getUserEntityByUserCredentials to make a duplicate of it and name it getEntityByUserCredentials

    Then, in the new duplicated function, find the below:

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

    And Replace it with:

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

    File: vendor\league\oauth2-server\src\Grant\PasswordGrant.php

    in : validateUser method add after $username and $password :

    $customProvider = $this->getRequestParameter('customProvider', $request);
    
    if (is_null($customProvider)) {
       throw OAuthServerException::invalidRequest('customProvider');
    }
    

    And this instead of the original line

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

    After doing this you'll be able to pass an extra key/value pair to your access token request, like for example:

    grant_type => password,
    client_id => someclientid
    client_secret => somesecret,
    username => someuser,
    password => somepass,
    client_scope => *,
    provider => driver-api // Or vendor-api
    

    I hope this will be helpful for you

    0 讨论(0)
提交回复
热议问题