diff --git a/src/Guard.php b/src/Guard.php index 60a7658a..993aeedb 100644 --- a/src/Guard.php +++ b/src/Guard.php @@ -14,6 +14,13 @@ class Guard */ protected $auth; + /** + * The provider name. + * + * @var string + */ + protected $provider; + /** * The number of minutes tokens should be allowed to remain valid. * @@ -26,12 +33,14 @@ class Guard * * @param \Illuminate\Contracts\Auth\Factory $auth * @param int $expiration + * @param string $provider * @return void */ - public function __construct(AuthFactory $auth, $expiration = null) + public function __construct(AuthFactory $auth, $expiration = null, $provider = null) { $this->auth = $auth; $this->expiration = $expiration; + $this->provider = $provider; } /** @@ -55,7 +64,8 @@ public function __invoke(Request $request) if (! $accessToken || ($this->expiration && - $accessToken->created_at->lte(now()->subMinutes($this->expiration)))) { + $accessToken->created_at->lte(now()->subMinutes($this->expiration))) || + ! $this->hasValidProvider($accessToken->tokenable)) { return; } @@ -77,4 +87,22 @@ protected function supportsTokens($tokenable = null) get_class($tokenable) )); } + + /** + * Determine if the Token Provider Correct. + * + * @param \Illuminate\Database\Eloquent\Model $tokenable + * @return bool + */ + protected function hasValidProvider($tokenable) + { + // If provider is null this method will return TRUE + if ($this->provider === null) { + return true; + } + + $model = config("auth.providers.{$this->provider}.model"); + + return $tokenable instanceof $model; + } } diff --git a/src/SanctumServiceProvider.php b/src/SanctumServiceProvider.php index ecee3fc6..706ebda0 100644 --- a/src/SanctumServiceProvider.php +++ b/src/SanctumServiceProvider.php @@ -2,6 +2,7 @@ namespace Laravel\Sanctum; +use Illuminate\Auth\RequestGuard; use Illuminate\Contracts\Http\Kernel; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Route; @@ -21,6 +22,7 @@ public function register() config([ 'auth.guards.sanctum' => array_merge([ 'driver' => 'sanctum', + 'provider' => null, ], config('auth.guards.sanctum', [])), ]); @@ -92,10 +94,29 @@ protected function defineRoutes() protected function configureGuard() { Auth::resolved(function ($auth) { - $auth->viaRequest('sanctum', new Guard($auth, config('sanctum.expiration'))); + $auth->extend('sanctum', function ($app, $name, array $config) use ($auth) { + return tap($this->registerGuard($auth, $config), function ($guard) { + $this->app->refresh('request', $guard, 'setRequest'); + }); + }); }); } + /** + * Register the guard. + * + * @param \Illuminate\Contracts\Auth\Factory $auth + * @param array $config + * @return RequestGuard + */ + protected function registerGuard($auth, $config) + { + return new RequestGuard( + new Guard($auth, config('sanctum.expiration'), $config['provider']), + $this->app['request'], + $auth->createUserProvider()); + } + /** * Configure the Sanctum middleware and priority. * diff --git a/tests/GuardTest.php b/tests/GuardTest.php index bef095ed..2d8ec85d 100644 --- a/tests/GuardTest.php +++ b/tests/GuardTest.php @@ -39,7 +39,7 @@ public function test_authentication_is_attempted_with_web_middleware() { $factory = Mockery::mock(AuthFactory::class); - $guard = new Guard($factory); + $guard = new Guard($factory, null, 'users'); $webGuard = Mockery::mock(stdClass::class); @@ -61,7 +61,7 @@ public function test_authentication_is_attempted_with_token_if_no_session_presen $factory = Mockery::mock(AuthFactory::class); - $guard = new Guard($factory); + $guard = new Guard($factory, null, 'users'); $webGuard = Mockery::mock(stdClass::class); @@ -86,7 +86,7 @@ public function test_authentication_with_token_fails_if_expired() $factory = Mockery::mock(AuthFactory::class); - $guard = new Guard($factory, 1); + $guard = new Guard($factory, 1, 'users'); $webGuard = Mockery::mock(stdClass::class); @@ -126,7 +126,7 @@ public function test_authentication_is_successful_with_token_if_no_session_prese $factory = Mockery::mock(AuthFactory::class); - $guard = new Guard($factory); + $guard = new Guard($factory, null); $webGuard = Mockery::mock(stdClass::class);