-
Notifications
You must be signed in to change notification settings - Fork 51
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
Fixed error getting two different instance using same token #72
Conversation
Are there any plans to merge this? |
@tmcnicholls Did you test it? It worked for you? |
@sfelix-martins I have the same issue in my custom solution based on suggestions in laravel/passport#161 I'm going to try this branch of your package now and will report back. |
@tmcnicholls I'm waiting your feedback. Thanks. |
@sfelix-martins I tested this branch and it doesn't work as expected for me. If I am authenticated with a bearer token for a user, I am able to access endpoints which should be restricted to app/Http/Kernel.php protected $routeMiddleware = [
...
'multiauth' => \SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate::class,
'oauth.providers' => \SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class,
...
]; config/auth.php 'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
'agent' => [
'driver' => 'passport',
'provider' => 'agents',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'agents' => [
'driver' => 'eloquent',
'model' => App\Models\Agent::class,
],
], routes/api.php Route::middleware('multiauth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::middleware('multiauth:agent')->get('/agent', function (Request $request) {
return $request->user();
});
Route::middleware('multiauth:agent')->get('/test', function (Request $request) {
return new JsonResponse(['data' => 'testing']);
}); models/Agent.php <?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use SMartins\PassportMultiauth\HasMultiAuthApiTokens;
use Spatie\Permission\Traits\HasRoles;
class Agent extends Authenticatable
{
use HasMultiAuthApiTokens, HasRoles, Notifiable;
} models/User.php <?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use SMartins\PassportMultiauth\HasMultiAuthApiTokens;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements MustVerifyEmail
{
use HasMultiAuthApiTokens, HasRoles, Notifiable;
} I can see in my database that access tokens are being stored with the correct provider. I started to xdebug the changes made to I should not be authenticated to access GET |
@tmcnicholls I wrote a tests to try simulate the error: <?php
namespace SMartins\PassportMultiauth\Tests\Feature;
use Illuminate\Http\Request;
use Laravel\Passport\Client;
use Illuminate\Support\Facades\Route;
use Laravel\Passport\Passport;
use SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider;
use SMartins\PassportMultiauth\Tests\Fixtures\Http\Kernel;
use SMartins\PassportMultiauth\Tests\TestCase;
use SMartins\PassportMultiauth\Tests\Fixtures\Models\User;
use SMartins\PassportMultiauth\Tests\Fixtures\Models\Company;
class MultiauthTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->loadLaravelMigrations(['--database' => 'passport']);
$this->artisan('migrate');
$this->artisan('key:generate');
$this->artisan('passport:install');
$this->withFactories(__DIR__.'/../Fixtures/factories');
$this->setAuthConfigs();
$this->setUpRoutes();
}
/**
* Resolve application HTTP Kernel implementation.
*
* @param \Illuminate\Foundation\Application $app
* @return void
*/
protected function resolveApplicationHttpKernel($app)
{
$app->singleton('Illuminate\Contracts\Http\Kernel', Kernel::class);
}
/**
* Setup auth configs.
*
* @return void
*/
protected function setAuthConfigs()
{
// Set up default entity
config(['auth.guards.api.driver' => 'passport']);
config(['auth.guards.api.provider' => 'users']);
config(['auth.providers.users.driver' => 'eloquent']);
config(['auth.providers.users.model' => User::class]);
// Set up company entity
config(['auth.guards.company.driver' => 'passport']);
config(['auth.guards.company.provider' => 'companies']);
config(['auth.providers.companies.driver' => 'eloquent']);
config(['auth.providers.companies.model' => Company::class]);
}
/**
* Create routes to tests authentication with guards and auth middleware.
*
* @return void
*/
public function setUpRoutes()
{
Route::group(['middleware' => AddCustomProvider::class], function () {
Passport::routes(function ($router) {
return $router->forAccessTokens();
});
});
Route::middleware('multiauth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::middleware('multiauth:company')->get('/company', function (Request $request) {
return $request->user();
});
}
/**
* @test
*/
public function it_will_return_401_when_try_access_route_with_company_guard_as_user()
{
// Two different models with same id.
$user = factory(User::class)->create();
$company = factory(Company::class)->create();
$this->assertEquals($user->getKey(), $company->getKey());
$client = Client::query()
->where(['password_client' => 1, 'revoked' => 0])
->first();
$params = [
'grant_type' => 'password',
'username' => $user->email,
'password' => 'secret',
'client_id' => $client->id,
'client_secret' => $client->secret,
'provider' => 'users',
];
$response = $this->json('POST', '/oauth/token', $params);
$accessToken = json_decode($response->getContent(), true)['access_token'];
$this->json('GET', '/company', [], ['Authorization' => 'Bearer '.$accessToken])
->assertStatus(401);
}
/**
* @test
*/
public function it_will_return_401_when_try_access_route_with_user_guard_as_company()
{
// Two different models with same id.
$user = factory(User::class)->create();
$company = factory(Company::class)->create();
$this->assertEquals($user->getKey(), $company->getKey());
$client = Client::query()
->where(['password_client' => 1, 'revoked' => 0])
->first();
$params = [
'grant_type' => 'password',
'username' => $company->email,
'password' => 'secret',
'client_id' => $client->id,
'client_secret' => $client->secret,
'provider' => 'companies',
];
$response = $this->json('POST', '/oauth/token', $params);
$accessToken = json_decode($response->getContent(), true)['access_token'];
$this->json('GET', '/user', [], ['Authorization' => 'Bearer '.$accessToken])
->assertStatus(401);
}
} tests/Feature/Fixtures/Kernel.php <?php
namespace SMartins\PassportMultiauth\Tests\Fixtures\Http;
use Orchestra\Testbench\Http\Kernel as HttpKernel;
use Orchestra\Testbench\Http\Middleware\RedirectIfAuthenticated;
class Kernel extends HttpKernel
{
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'multiauth' => \SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate::class,
'oauth.providers' => \SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
} tests/Feature/Fixtures/User.php <?php
namespace SMartins\PassportMultiauth\Tests\Fixtures\Models;
use SMartins\PassportMultiauth\HasMultiAuthApiTokens;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $table = 'users';
use HasMultiAuthApiTokens;
public function getAuthIdentifierName()
{
return 'id';
}
} test/Feature/Fixtures/Company.php <?php
namespace SMartins\PassportMultiauth\Tests\Fixtures\Models;
use SMartins\PassportMultiauth\HasMultiAuthApiTokens;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Company extends Authenticatable
{
protected $table = 'companies';
use HasMultiAuthApiTokens;
public function getAuthIdentifierName()
{
return 'id';
}
} But a can't simulate the error. All tests passed correctly. I'm using orchestra/testbench to help me on tests. Can you check if there is something wrong? I'll install in a fresh package and try simulate your same example. |
@sfelix-martins I'll pull your tests into my project and xdebug to try and see what is happening differently. Thanks |
@sfelix-martins I found the cause of the issue. In a default Laravel installation, the default guard is set to However, if you set your default guard to a valid Try adding this to config(['auth.defaults.guard' => 'api']); or config(['auth.defaults.guard' => 'company']); This is happening because Test results:
|
@tmcnicholls Thanks! I'll check it ASAP. |
Hi @sfelix-martins, did you make any progress on this? Thanks |
@tmcnicholls I’m sorry. Nothing yet. A pull request would be welcome! Thanks. |
…avior in execution time
@tmcnicholls I analysed ways to finally fix this problem, and I think that I found the solution with your help. But it will broke the compatibility with older versions of the package. I will close this pull request and create a pre-release to version 5.0. If you want help me test it you can: Just follow this upgrade guide. Thanks! |
@sfelix-martins thanks for your work on this. I'll test the pre-release changes and let you know if it works for me. |
Fix #63
Probably fix #51
It extends the
Auth
to driverpassport
after Laravel Passport authenticate the users and check whats the correct user to be logged, based on guards passed on middleware.The user resolver on request too was changed to check the correct logged user.