laravel / passport

Laravel Passport provides OAuth2 server support to Laravel.
https://laravel.com/docs/passport
MIT License
3.29k stars 780 forks source link

Passport Multi-Auth #161

Closed SidharthRaveendran closed 4 years ago

SidharthRaveendran commented 8 years ago

Would passport be implementing Multi-Auth system? or is there another way to incorporate the multi-auth into the app.

I have created Multiple Models which use Laravel's Auth system to implement proper multi-auth system. I'm not sure how to use passport for the same.

eepawan commented 7 years ago

I am also looking for same. Anyone here to help?

jenky commented 7 years ago

https://github.com/laravel/passport/blob/7ed1a0b80c1da9a3bf25eb180068ddd005a82068/src/Bridge/UserRepository.php#L35

This package always uses users provider model in config/auth to authenticate, so I guess there are no hacks for now?

yanko-belov commented 7 years ago

+1

gauravmak commented 7 years ago

With #216 , it is dynamic now so multiple guards can be added and used with passport now I believe.

SidharthRaveendran commented 7 years ago

Still we cannot implement multi-auth using laravel using this update.

zubair1 commented 7 years ago

I managed to get access tokens from different auth providers in laravel, but I had to modify:


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


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


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 => api

In this example, I set provider to 'api', which is default. But now I can pass other auth providers as part of the request. So, just to show another example, I could do the following:

grant_type => password,
client_id => someclientid
client_secret => somesecret,
username => someuser,
password => somepass,
client_scope => *,
provider => api_admins

Now I used 'api_admins' auth provider to authenticate tokens.

P.S: I replaced the functions with new ones instead of overwriting because there was another third-party library involved league\oauth2-server, besides the laravel/passport library. If I were to recommend a proper way to implement this would be to extend the getUserEntityByUserCredentials function so that it could accept our new argument, but for that you would have to overwrite the interface function definition too, it's located at vendor\league\oauth2-server\src\Repositories\RepositoryInterface.php

Hope this helps someone else

MohammedSabbah commented 7 years ago

@zubair1 zubair1 I have tried your method and it worked, let me rewrite the steps more clearly,

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

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

3) Try it with Postman with the following:

url: http://127.0.0.1:8000/oauth/token Headers: Content-Type: application/json

body:

{
"username":"test@gmail.com",
"password":"secret",
"grant_type": "password",
    "client_id": 2,
    "client_secret": "string",
    "theNewProvider": "admin"
}

Do not forget to do the following as well:

reisnobre commented 7 years ago

Nothing new until now?

renanwilliam commented 7 years ago

I have made a very simple hack to do it:

1) Add a new custom user provider in config/auth.php using a model that extends Authenticatable class and use HasRoles, HasApiTokens traits.

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session", "token"
    |
    */

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

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

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Administrator::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that the reset token should be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],

        'admins' => [
            'provider' => 'admins',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

2) Create a new custom middleware PassportCustomProvider like that:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Config;

class PassportCustomProvider
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $params = $request->all();
        if (array_key_exists('provider', $params)) {
            Config::set('auth.guards.api.provider', $params['provider']);
        }
        return $next($request);
    }
}

3) Register the middleware as a route middleware:

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'passport-administrators' => \App\Http\Middleware\PassportCustomProvider::class,
    ];
}

4) Encapsulate the passport routes with this middleware in AuthServiceProvider:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Route::group(['middleware' => 'passport-administrators'], function () {
            Passport::routes();
        });
    }

}

5) Add the 'provider' param in your request at /oauth/token:

POST /oauth/token HTTP/1.1
Host: localhost
Accept: application/json, text/plain, */*
Content-Type: application/json;charset=UTF-8
Cache-Control: no-cache

{
    "username":"user@domain.com",
    "password":"password",
    "grant_type" : "password",
    "client_id": "client-id",
    "client_secret" : "client-secret",
    "provider" : "admins"
}

The problem after this step is the token saved in oauth_access_tokens only contains the administrator ID. When we use the token received to authenticate, it not look at Administrator models.

renanwilliam commented 7 years ago

Complementing the above comment, to make it functional for Bearer tokens it's necessary the following steps:

6) Create a migration to save the relationship between access tokens and providers:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class OauthAccessTokenProviders extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('oauth_access_token_providers', function (Blueprint $table) {
            $table->string('oauth_access_token_id', 100)->primary();
            $table->string('provider');
            $table->timestamps();

            $table->foreign('oauth_access_token_id')
                ->references('id')->on('oauth_access_tokens')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('oauth_access_token_providers');
    }
}

7) Add a event listener in EventServiceProvider:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'Laravel\Passport\Events\AccessTokenCreated' => [
            'App\Listeners\PassportAccessTokenCreated',
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
    }
}

8) Put this following code in your listener, to save the relationship between access tokens and providers:

<?php

namespace App\Listeners;

use App\Events\Laravel\Passport\Events\AccessTokenCreated;
use Carbon\Carbon;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class PassportAccessTokenCreated
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  \Laravel\Passport\Events\AccessTokenCreated $event
     * @return void
     */
    public function handle(\Laravel\Passport\Events\AccessTokenCreated $event)
    {
        $provider = \Config::get('auth.guards.api.provider');
        DB::table('oauth_access_token_providers')->insert([
            "oauth_access_token_id" => $event->tokenId,
            "provider" => $provider,
            "created_at" => new Carbon(),
            "updated_at" => new Carbon(),
        ]);
    }
}

9) Create a new global middleware to handle the custom providers setup for each request:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\DB;
use League\OAuth2\Server\ResourceServer;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;

class PassportCustomProviderAccessToken
{

    private $server;

    public function __construct(ResourceServer $server)
    {
        $this->server = $server;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $psr = (new DiactorosFactory)->createRequest($request);

        try {
            $psr = $this->server->validateAuthenticatedRequest($psr);
            $token_id = $psr->getAttribute('oauth_access_token_id');
            if ($token_id) {
                $access_token = DB::table('oauth_access_token_providers')->where('oauth_access_token_id',
                    $token_id)->first();

                if ($access_token) {
                    \Config::set('auth.guards.api.provider', $access_token->provider);
                }
            }
        } catch (\Exception $e) {

        }

        return $next($request);
    }
}

10) Finally, register your middleware as global HTTP middleware at app/Http/Kernel

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\PassportCustomProviderAccessToken::class
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'passport-custom-provider' => \App\Http\Middleware\PassportCustomProvider::class
    ];
}

It's only missing the refresh token and the cookie login handles.

ghulamali2612 commented 7 years ago

@zubair1 Thanks Zubair your solution worked.

zubair1 commented 7 years ago

@MohammedSabbah - Glad it worked for you and thanks for simplifying the steps. I hope it helps others out.

@ghulamali2612 - You're welcome, glad it helped :)

sanprodev commented 7 years ago

@zubair1, @MohammedSabbah, @ghulamali2612

Your Solution Works, i can get access token for Admin model, but when i test it in post man http://localhost:8000/api/user i'm getting the user of User model not the Admin models uses

https://stackoverflow.com/questions/44903323/laravel-api-returning-different-model-user

thank you

ElioTohm commented 7 years ago

@sanprodev In config/auth.php under guards -> api change the provider to Admin 'api' => [ 'driver' => 'passport', 'provider' => 'admin ', //in the link provided it's client ],

rockmantist commented 7 years ago

@renanwilliam i've followed your step and managed to get multi auth passport working.

but i found another problem when using javascript client, i always get unauthenticated error for Admin auth. i use Consuming Your API with Javascript (section from laravel 5.4 docs) and have added \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class to the new guard but still no luck.

anyone facing same problem here ?

renanwilliam commented 7 years ago

Hi @rockmantist.

The token was not validated in PassportCustomProviderAccessToken middleware?:

try {
      $psr = $this->server->validateAuthenticatedRequest($psr); //is it validated here?
      $token_id = $psr->getAttribute('oauth_access_token_id');
      if ($token_id) {
         $access_token = DB::table('oauth_access_token_providers')->where('oauth_access_token_id', 
         $token_id)->first();

         if ($access_token) {
             \Config::set('auth.guards.api.provider', $access_token->provider);
          }
      }
} catch (\Exception $e) { }
matiazar commented 7 years ago

Hi.. thanks 4 all... but what about when passport make any changes to their code.. and you made a composer update? It will overwrite all your files.. and your app will be down. Im right?!

renanwilliam commented 7 years ago

@matiazar using the approach that I described above there's no changes in passport code

storesbuzz commented 7 years ago

Thanks @MohammedSabbah it worked for login. But facing issue with posting data. Will there a change in token passing while posting data?

storesbuzz commented 7 years ago

Hi @rockmantist does it worked for you?

rockmantist commented 7 years ago

@renanwilliam sorry for the late reply, using the middleware above didn't work. i end up creating a new middleware, it's basically the exact same as CreateFreshApiToken but i modified it to force using my other guard (admin).

the only problem now is, it still authenticated on another guard, for example i perform authentication on guard web, get the token, try to authenticate to admin guard, it's authenticated (i guess it's because both have the same row with same id or primary key value).

Fahad032 commented 7 years ago

@rockmantist does the guard means auth()->guard('admin')->user() here, I am searching for a solution and just reached here.

rockmantist commented 7 years ago

@Fahad032 in my case it's guard auth()->guard('auth:api')->user() for frontend and auth()->guard('auth:api_admin')->user() for admin.

Sharvadze commented 7 years ago

+1 Same problem here, can't use passport for other provider

VitruxPT commented 7 years ago

What about being able to change login or impersonate other users with passport? I have one app that needs to make requests in the name of the user and I can't use their access tokens since the value is different on the database, and I also can't use Auth::once or Auth::onceById while in the auth:api middleware. The user doesn't login to that App, but I still need the app to be able to execute actions to my API just like if it was the user.

For example, just checking a user in my api with that app:

So in the end, that endpoint would show the info from user 12345 instead of my app's account info.

storesbuzz commented 7 years ago

Laravel passport is only working with User as a provider. Even if you fetch token by adding above changes Post and get requests are not working with changed passport provider than User.

Better you create multi auth with session driver and let 'User' model only for passport. Repo here https://github.com/storesbuzz/laravel-multiAuth

sanprodev commented 7 years ago

@storesbuzz The above approach with provider parameter works fine with all the CRUD methods.i have implemented in 2 projects which are in production.

rbuckingham commented 7 years ago

anyone see a simpler solution for just the laravel_token cookie functionality of Passport (https://laravel.com/docs/5.5/passport#consuming-your-api-with-javascript) as I don't need the whole Oauth token functionality.

Laravel_token auth to my api works for my regular users but I dont think I can get the laravel_token cookie added for my multiauth 'admins' that use a different guard provider and model without doing something really ugly, I'm hoping for this functionality only I can do something cleaner.

sowork commented 7 years ago

@renanwilliam I think the PassportCustomProviderAccessToken kernel class middlewareGroups inside the best bar 'api' => [              \ App \ Http \ Middleware \ PassportAccessTokenValidate :: class,              'throttle: 60,1',              'bindings',          ],

renanwilliam commented 7 years ago

Hi @sowork ,

I use some routes that are not only in api so that's the reason to keep globally

sowork commented 7 years ago

@renanwilliam Yes, but your idea is really a good idea

renanwilliam commented 7 years ago

Thanks @sowork! I will try create a package to make it work's painless

sfelix-martins commented 7 years ago

I made a package based on responses from @renanwilliam to solve this. I hope it helps!

jsdecena commented 7 years ago

Hello, I also created a small package for this: https://github.com/jsdecena/laravel-passport-mutiauth Hope it helps :)

LG0012 commented 7 years ago

Still not working

SamitoX4 commented 7 years ago

@sfelix-martins Use your package and if you generate access tokens but when I use a postman to obtain the user's data, 404 error appears, I also wanted to ask where or how to configure this part:

sfelix-martins commented 7 years ago

@SamitoX4 When you use the middleware group defined in your app/Http/Kernel encapsulating your Passport::routes. e.g:

class AuthServiceProvider extends ServiceProvider
{
    ...

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
        // Encapsulated access token routes
        Route::group(['middleware' => 'custom-provider'], function () {
            Passport::routes(function ($router) {
                return $router->forAccessTokens();
            });
        });
    }
    ...
}

The middleware will be configure the guard api with provider defined on route to create an access_token: config(['auth.guards.api.provider' => $accessToken->provider])

For this reason you can pass the guard to obtains the entity authenticated. For example:

To get the user logged using the Illuminate\Http\Request you need the guard api:

class CompanyController extends Controller { public function me(Request $request) { // To get authenticatable entity using the guard $entity = $request->user('api')

    // If your access token passed to your `/company` route was created with `provider` param `companies`, for example, your entity is an instance of `Company`
    return $entity instanceof Company // true
}

}


You can use still the facade `Auth` to get the authenticatable entity passing the guard like in the previous sample:

```php
use App\Company;
use Illuminate\Http\Request;
use Auth;

class CompanyController extends Controller
{
    public function me(Request $request)
    {
        // To get authenticatable entity using the guard
        $entity = Auth::guard('api')->user();

        // If your access token passed to your `/company` route was created with `provider` param `companies`, for example, your entity is an instance of `Company`
        return $entity instanceof Company // true
    }
}

I hope it helps!

SamitoX4 commented 7 years ago

@sfelix-martins Thank you very much for your response, I'll see how it goes! ... good day.

sfelix-martins commented 7 years ago

@SamitoX4 if you wish you can create an issue on package repository. Good day.

jaysongyn commented 6 years ago

@zubair1 Thank you! your solution is working. Do you know any way to test using phpunit? I tried: Passport::actingAs(factory('App\Admin')->create(), [], 'admin-api'); result error: Expected status code 200 but received 401.

sfelix-martins commented 6 years ago

@jaysongyn I don't know that if you already solved your problem to unit test, but I tested here any possibilities:

If you set the guard of user logged ('admin-api' in your case) you need pass too the same guard on method that your auth middleware. Example:

Route::group(['middleware' => 'auth:admin-api'], function ($request) {
    return $request->user(); // or passing the guard `$request->user('admin-api');
}
andrewmclagan commented 6 years ago

All these hacks and fixes are irrelevant. We should be writing PRs to update the original package rather then work-arounds. Thats the idea behind open source.

minute-med commented 6 years ago

@andrewmclagan still waiting your PR ... @sfelix-martins thanks for your cool package

prodigy7 commented 6 years ago

Any news here? Passport multiauth feature like Tymon\JWTAuth it does is a very useful and necessary feature for more complex projects. So far, a important feature for me, porting Tymon\JWTAuth to passport (see https://stackoverflow.com/questions/41376928/laravel-5-3-passport-jwt-authentication) and let code like this still working:

if (!$token = auth()->guard('api-admin')->attempt($credentials)) {
    return response()->json(['message' => 'Invalid credentials'], 422);
}
iamriajul commented 6 years ago

I have done this using this technique:

My Admin API Url: https://example.com/api/login My Customer API Url: https://example.com/api.customer/login

adding this to any ServiceProvider (I have added in RouteServiceProvider.php before Customer custom route) ` // Fix/Support for multiple user with different table by changing provider on customer-api circumstances

    Config::set('auth.guards.api.provider', request()->input('provider', starts_with(request()->path(), 'api.customer') ? 'customers' : 'users'));`

and must add your custom provider in providers array in config/auth.php 'customers' => [ 'driver' => 'eloquent', 'model' => App\Customer::class, ],

ryzr commented 6 years ago

I solved this by using a forked version of Passport and middleware. The middleware allows me to select the provider based on route:

public function handle($request, Closure $next, $provider = null)
    {
        if ($provider) {
            $apiProvider = config('auth.guards.api.provider');

            config()->set('auth.providers.' . $apiProvider . '.model', config('auth.providers.' . $provider . '.model'));
        }

        return $next($request);
    }
Route::middleware('provider:athletes')->group(function() {
    Route::middleware('auth:api')->group(function () {
        Route::get('authenticated-stuff', 'Api\ApiController@authenticatedStuff');
    });

    Route::get('guest-stuff', 'Api\ApiController@guestStuff');
});

I've then stored all access tokens, codes etc as polymorphic relationships in the database, e.g.

'user_type' => (new $model)->getMorphClass(),

This required edits to Bridge\AccessTokenRepository, Bridge\AuthCodeRepository, ClientRepository, TokenRepository and HasApiTokens.

I feel that this has given me the most control.

sowork commented 6 years ago

Config::set('auth.guards.api.provider', 'provider')

Only API access is normal, but when the user accesses using guard(web), the provider ofguard(web) cannot be updated normally.

->middleware('auth:api,web') Config::set('auth.guards.{$api|$web}.provider', 'provider') {$api|$web} Unable to distinguish between currently used guard

osman-mohamad commented 6 years ago

any news about this feature ?

osman-mohamad commented 6 years ago

I used @zubair1 method to handle multi auth with passport. first I cloned passport repository and league/oauth2-server repository . updated them as needed . changed composer config to use the forks . and updated my packages. then the login working well .

but the main problem is with the tokens relationships with the user table . how to fix this ?

sowork commented 6 years ago

Can this provider be stored in access_token