-
Notifications
You must be signed in to change notification settings - Fork 785
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[9.x] Initial support for multiple providers #1220
Conversation
Hey @billriess. Thanks a lot for giving this another go! I've marked the PR as draft because some tests are still failing. Let's get those fixed first before we mark it as ready. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gave this a quick review. In general this looks good. But I believe the PR should definitely go to master because of the breaking changes.
Thanks for your work already!
Co-Authored-By: Dries Vints <[email protected]>
I fixed DocBlocks and StyleCI suggestions as well as updated the way the provider defaults when using the artisan command. I will take a look at the failed tests later. I encourage anyone interested in this feature to review it and make suggestions as needed. |
Can someone describe what "multi-provider" even means? |
@taylorotwell inside the |
@taylorotwell as @lucadegasperi has explained the current implementation Passport is fairly restrictive when using things like password grants. This PR allows us to define what provider should be used at the oauth_client level. This way, we can have separate oauth_clients for different providers, which trickles down to different models. This also fixes a potential security concern as Passport defaults to passing in the provider from the request's guard. This means the Authenticable returned by Passport would be whatever middleware guard you had in place on the route - allowing a |
I've just pushed another update that fixes some of the tests. I'm a little stumped on the remaining failed tests as they are related to the way the PSR is mocked. If anyone has some ideas on how I can get those last tests to pass I would appreciate it. |
Fixed the validation on the TokenGuard to fall back properly if a provider is not set on the oauth_client. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think we're almost there. Nice work already 👍
I'm confused. Where in this code does it actually use the Client model's provider to pull the model from the database. I see the PassportUserProvider provider name is compared to the clients. But PassportUserProvider's provider is always set to $config['provider']... which appears to be some static value and not controlled by the client being used at all. I guess I'm lost? What is my actual auth configuration file supposed to look like when using this? I guess I am supposed to define a different guard in my auth configuration file each type of client provider I have? |
If the requested provider matches the one on the client then we know we can let them in and return the user. If there is a mismatch, we know that the token they are using is not setup for whatever provider you're trying to guard against.
...
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users'
],
'api:customers' => [
'driver' => 'passport',
'provider' => 'customers'
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'customers' => [
'driver' => 'eloquent',
'model' => App\Customer::class,
],
],
// This should only be accessible by Users...
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
// This should only be accessible by Customers...
Route::middleware('auth:api:customers')->get('/customer', function (Request $request) {
return $request->user();
}); |
Gotcha. |
Thanks. We'll want some documentation around this. |
Thanks @billriess for all your work on this! |
For my existing oauth_clients do I need to put in a value of 'users' in the provider column for them? Since the default provider in config/auth.php is 'users' |
@ziming no, the column is nullable (see upgrade guide) and will take the default provider if it's set as null. |
how can we add this change to our project? |
@driesvints
it returns the customer's info and for user's routes it works fine and it return the user's info too but I think there is a bug about tokens
It return customer's info again |
Did you set the provider on the client? |
@billriess
and for the user and courier's model I did like this :
and the api.php :
everything is fine but in postman i can use courier token for user's routes and use user token for courier's routes too |
In your database |
no the provider column does not exist in the table and I ran the
and it didn't add to table by migration |
@sajad2176 please read the upgrade guide: https://github.com/laravel/passport/blob/9.x/UPGRADE.md#support-for-multiple-guards |
@billriess @driesvints I still think there is an issue - I have my providers set in auth.php, the provider column added. On LoginController with no middleware set, it uses users model. This is working as expected. The issue starts here. When I change the guard to use
It's still using the users model not the managers model. In the auth.php file I have a guard
Am I missing something. I created a new client-id, client-secret with a provider column pointing to managers. Edit: |
Some things to note: This PR covers password grants for bearer tokens. If you're not using that flow, it won't do anything new than it did previously. You must have the provider defined to force that provider to be used. In your case, |
@billriess I am using bearer tokens. This is my guzzle request after the client calls the login route
And like I mentioned above, I do have a client_id, client_secret and provider for the managers table. The login is not working for a different provider other than the USER model or are you saying the Login route wont work but everything after the bearer token has been issued will EDIT: Its working |
@heyaj19 Glad to see you got it working. |
This feature is working great. Thank you very much for making it. However, from what I understand, it only works with password grant tokens access type (which is now deprecated). Is there any chance that it is extended to the standard OAuth2 authorization code redirect flow ? |
@gilles6 Thanks, glad to see it's working well for you! I don't see why this couldn't be extended to work with any other part of Passport. Given that the OAuth2 spec is moving away from Password grants we could see authorization code flow become more used. I don't have a lot of free time at the moment but I can keep this on my things to look at once I get some time. |
@billriess That would be great :-) Let me know, I'd be one of your first testers! |
How can I do in my login method? Because "message": "Method Illuminate\Auth\RequestGuard::attempt does not exist.", |
@guianzollin |
@billriess |
I have same problem. multi-auth only work with session.If that the token does not work. |
This PR adds support to allow passport to use and enforce multiple providers.
The issue:
Currently, Passport only uses the
UserProvider
passed into it from theRequestGuard
. This can be problematic if you have more than one provider (config/auth.php) that needs to be authenticated. Since Passport has no knowledge of otherUserProvider
you can end up in situations where the wrong user is authenticated and returned.The solution:
This PR adds support to optionally set the provider that should be used on the
Passport\Client
. If a provider is defined on thePassport\Client
, it will compare it against theUserProvider
coming in from theRequestGuard
and return the user if they match. This ensures that the user being returned is coming from the right model. If there is a mismatch, no user is returned, thus leaving you with an unauthenticated request. If no provider is defined on thePassport\Client
then everything works as it always has.Breaking changes:
The only big breaking change here is that this requires a schema change to the
oauth_clients
table to add theprovider
column.