Change version on composer.json
:
"smartins/passport-multiauth": "^5.0",
Update using composer:
$ composer update smartins/passport-multiauth
To all works fine, we need to ensure that the SMartins\PassportMultiauth\Providers\MultiauthServiceProvider::class
service provider
be registered before Laravel\Passport\PassportServiceProvider::class
.
Firstly, you will remove the laravel/passport
package from Laravel Package Discovery.
In your composer.json
file, add the laravel/passport
to extra.laravel.dont-discover
array:
"extra": {
"laravel": {
"dont-discover": [
"laravel/passport"
]
}
},
And register the providers manually on config/app.php
:
'providers' => [
// ...
SMartins\PassportMultiauth\Providers\MultiauthServiceProvider::class,
Laravel\Passport\PassportServiceProvider::class,
],
WARNING: The provider SMartins\PassportMultiauth\Providers\MultiauthServiceProvider::class
MUST be added before Laravel\Passport\PassportServiceProvider::class
to it works fine.
Clear the bootstrap cache files to re-register the providers:
php artisan optimize:clear
You just should asserts that your requests to routes wrapped by middleware \SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class
has the provider
param passing the desired provider.
E.g.:
In version 2.0
if your request to oauth/token
don't has the param provider, the default provider defined on config('auth.guards.api.provider')
will be used.
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":"[email protected]",
"password":"password",
"grant_type" : "password",
"client_id": "client-id",
"client_secret" : "client-secret"
}
The response to request above should be a 200 OK
with access token on body.
In version 3.0
the request above will return a 400 Bad Request
{
"message": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.",
"exception": "League\\OAuth2\\Server\\Exception\\OAuthServerException",
"file": "/home/vagrant/code/vendor/league/oauth2-server/src/Exception/OAuthServerException.php",
"line": 114,
"trace": []
}
To fix it you should pass the provider param on request even for the provider defined in the api
guard. E.g.:
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":"[email protected]",
"password":"password",
"grant_type" : "password",
"client_id": "client-id",
"client_secret" : "client-secret",
"provider": "users"
}
In short, the param provider
is required and must exists on config/auth.php
providers config.
Update the smartins/passport-multiauth
dependency to ^2.0
in your composer.json
file.
OBS: If you have problems using laravel/passport
2.0.*
please update to >= 3.0
.
On app/Http/Kernel.php
remove the SMartins\PassportMultiauth\Http\Middleware\ConfigAccessTokenCustomProvider
from your middlewares.
Now you need just of SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class
to use in your forAccessTokens
Laravel/Passport
routes. Replace the default auth
middleware from Illuminate\Auth\Middleware\Authenticate::class
to SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate::class
:
class Kernel extends HttpKernel
{
// ...
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
// ** Replace auth middleware **
// 'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth' => \SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate::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,
// Keep the `AddCustomProvider`
'oauth.providers' => \SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
// ...
}
- Change the middleware on
Laravel\Passport
routes onAuthServiceProvider
:
namespace App\Providers;
use Route;
use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
// ...
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
// Middleware `oauth.providers` middleware defined on $routeMiddleware above
Route::group(['middleware' => 'oauth.providers'], function () {
Passport::routes(function ($router) {
return $router->forAccessTokens();
});
});
}
// ...
}
On v2.0
you don't need to pass the guard api
to routes that has multi-auth guard. E.g.:
- On
v1.0
to use more than one guard onauth
middleware you should do something like:
Route::middleware('auth:admin,api')->get('users', function (Request $request) {
return $request->user('api'); // Return an instance of `Admin` or `User`
});
// Or to just one guard with not default middleware (api):
Route::middleware('auth:admin')->get('admin', function (Request $request) {
return $request->user('admin');
});
- On
v2.0
in all cases you can use$request->user()
, without the guard. E.g.:
Route::middleware('auth:admin,api')->get('users', function (Request $request) {
return $request->user(); // Returns an instance of `Admin` or `User`
});
// Or to just one guard with not default middleware (api):
Route::middleware('auth:admin')->get('admin', function (Request $request) {
return $request->user(); // Returns an instance of `Admin`
});
Route::middleware('auth:admin,api,customer')->get('users', function (Request $request) {
// You can specify the guard
return $request->user('customer'); // Returns an instance of `Customer` or `null`
});
- You can use too the
Auth
facade:
Auth::check();
Auth::user();
On older major release (v1.0), to use scopes you should replace the Laravel\Passport
scopes middlewares to package middlewares:
// On version 1.0.
'multiauth.scope' => \SMartins\PassportMultiauth\Http\Middleware\MultiAuthCheckForAnyScope::class,
'multiauth.scopes' => \SMartins\PassportMultiauth\Http\Middleware\MultiAuthCheckScopes::class,
On version 2.0 you must do the opposite way. Just uses the default middlewares from Larave\Passport
:
// On version 2.0.
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
Read more about laravel passport scopes on official docs
Instead to use the Laravel\Passport\Passport::actingAs()
method, use SMartins\PassportMultiauth\PassportMultiauth::actingAs()
.
The difference is that the actingAs
from this package get the guard based on Authenticatable
instance passed on first parameter and authenticate this user using your guard. E.g.:
use App\User;
use Tests\TestCase;
use SMartins\PassportMultiauth\PassportMultiauth;
class AuthTest extends TestCase
{
public function fooTest()
{
$user = factory(User::class)->create();
PassportMultiauth::actingAs($user);
$this->json('GET', 'api/user');
}
}