Skip to content

Commit

Permalink
Added dispatching of authentication events. The PR was originally cre…
Browse files Browse the repository at this point in the history
…ated here tymondesigns/jwt-auth#2137 by fkupper
  • Loading branch information
eschricker committed Oct 6, 2021
1 parent 4314ea3 commit 71ef3e6
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 11 deletions.
90 changes: 84 additions & 6 deletions src/JWTGuard.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
namespace PHPOpenSourceSaver\JWTAuth;

use BadMethodCallException;
use Illuminate\Auth\Events\Attempting;
use Illuminate\Auth\Events\Failed;
use Illuminate\Auth\Events\Validated;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Http\Request;
use Illuminate\Support\Traits\Macroable;
use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;
Expand Down Expand Up @@ -48,6 +52,20 @@ class JWTGuard implements Guard
*/
protected $request;

/**
* The event dispatcher instance.
*
* @var \Illuminate\Contracts\Events\Dispatcher
*/
protected $events;

/**
* The name of the Guard.
*
* @var string
*/
protected $name = 'tymon.jwt';

/**
* Instantiate the class.
*
Expand All @@ -57,11 +75,12 @@ class JWTGuard implements Guard
*
* @return void
*/
public function __construct(JWT $jwt, UserProvider $provider, Request $request)
public function __construct(JWT $jwt, UserProvider $provider, Request $request, Dispatcher $eventDispatcher)
{
$this->jwt = $jwt;
$this->provider = $provider;
$this->request = $request;
$this->events = $eventDispatcher;
}

/**
Expand All @@ -75,7 +94,8 @@ public function user()
return $this->user;
}

if ($this->jwt->setRequest($this->request)->getToken() &&
if (
$this->jwt->setRequest($this->request)->getToken() &&
($payload = $this->jwt->check(true)) &&
$this->validateSubject()
) {
Expand All @@ -92,7 +112,7 @@ public function user()
*/
public function userOrFail()
{
if (! $user = $this->user()) {
if (!$user = $this->user()) {
throw new UserNotDefinedException;
}

Expand Down Expand Up @@ -123,10 +143,14 @@ public function attempt(array $credentials = [], $login = true)
{
$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

$this->fireAttemptEvent($credentials);

if ($this->hasValidCredentials($user, $credentials)) {
return $login ? $this->login($user) : true;
}

$this->fireFailedEvent($user, $credentials);

return false;
}

Expand Down Expand Up @@ -387,7 +411,13 @@ public function getLastAttempted()
*/
protected function hasValidCredentials($user, $credentials)
{
return $user !== null && $this->provider->validateCredentials($user, $credentials);
$validated = $user !== null && $this->provider->validateCredentials($user, $credentials);

if ($validated) {
$this->fireValidatedEvent($user);
}

return $validated;
}

/**
Expand All @@ -399,7 +429,7 @@ protected function validateSubject()
{
// If the provider doesn't have the necessary method
// to get the underlying model name then allow.
if (! method_exists($this->provider, 'getModel')) {
if (!method_exists($this->provider, 'getModel')) {
return true;
}

Expand All @@ -415,13 +445,61 @@ protected function validateSubject()
*/
protected function requireToken()
{
if (! $this->jwt->setRequest($this->getRequest())->getToken()) {
if (!$this->jwt->setRequest($this->getRequest())->getToken()) {
throw new JWTException('Token could not be parsed from the request.');
}

return $this->jwt;
}

/**
* Fire the attempt event.
*
* @param array $credentials
*
* @return void
*/
protected function fireAttemptEvent(array $credentials)
{
$this->events->dispatch(new Attempting(
$this->name,
$credentials,
false
));
}

/**
* Fires the validated event.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
*
* @return void
*/
protected function fireValidatedEvent($user)
{
$this->events->dispatch(new Validated(
$this->name,
$user
));
}

/**
* Fire the failed authentication attempt event.
*
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
* @param array $credentials
*
* @return void
*/
protected function fireFailedEvent($user, array $credentials)
{
$this->events->dispatch(new Failed(
$this->name,
$user,
$credentials
));
}

/**
* Magically call the JWT instance.
*
Expand Down
3 changes: 2 additions & 1 deletion src/Providers/AbstractServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ protected function extendAuthGuard()
$guard = new JWTGuard(
$app['tymon.jwt'],
$app['auth']->createUserProvider($config['provider']),
$app['request']
$app['request'],
$app['events']
);

$app->refresh('request', $guard, 'setRequest');
Expand Down
57 changes: 56 additions & 1 deletion tests/JWTGuardTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
namespace PHPOpenSourceSaver\JWTAuth\Test;

use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Auth\Events\Attempting;
use Illuminate\Auth\Events\Failed;
use Illuminate\Auth\Events\Validated;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Http\Request;
use Mockery;
Expand Down Expand Up @@ -41,13 +45,24 @@ class JWTGuardTest extends AbstractTestCase
*/
protected $guard;

/**
* @var \lluminate\Contracts\Events\Dispatcher|\Mockery\MockInterface
*/
protected $eventDispatcher;

public function setUp(): void
{
parent::setUp();

$this->jwt = Mockery::mock(JWT::class);
$this->provider = Mockery::mock(EloquentUserProvider::class);
$this->guard = new JWTGuard($this->jwt, $this->provider, Request::create('/foo', 'GET'));
$this->eventDispatcher = Mockery::mock(Dispatcher::class);
$this->guard = new JWTGuard(
$this->jwt,
$this->provider,
Request::create('/foo', 'GET'),
$this->eventDispatcher
);
}

/** @test */
Expand Down Expand Up @@ -206,6 +221,14 @@ public function it_should_return_a_token_if_credentials_are_ok_and_user_is_found
->with(['foo' => 'bar'])
->andReturnSelf();

$this->eventDispatcher->shouldReceive('dispatch')
->once()
->with(Mockery::type(Attempting::class));

$this->eventDispatcher->shouldReceive('dispatch')
->once()
->with(Mockery::type(Validated::class));

$token = $this->guard->claims(['foo' => 'bar'])->attempt($credentials);

$this->assertSame($this->guard->getLastAttempted(), $user);
Expand All @@ -228,6 +251,14 @@ public function it_should_return_true_if_credentials_are_ok_and_user_is_found_wh
->with($user, $credentials)
->andReturn(true);

$this->eventDispatcher->shouldReceive('dispatch')
->twice()
->with(Mockery::type(Attempting::class));

$this->eventDispatcher->shouldReceive('dispatch')
->twice()
->with(Mockery::type(Validated::class));

$this->assertTrue($this->guard->attempt($credentials, false)); // once
$this->assertTrue($this->guard->validate($credentials)); // twice
}
Expand All @@ -248,6 +279,14 @@ public function it_should_return_false_if_credentials_are_invalid()
->with($user, $credentials)
->andReturn(false);

$this->eventDispatcher->shouldReceive('dispatch')
->once()
->with(Mockery::type(Attempting::class));

$this->eventDispatcher->shouldReceive('dispatch')
->once()
->with(Mockery::type(Failed::class));

$this->assertFalse($this->guard->attempt($credentials));
}

Expand Down Expand Up @@ -348,6 +387,14 @@ public function it_should_authenticate_the_user_by_credentials_and_return_true_i
->with($user, $credentials)
->andReturn(true);

$this->eventDispatcher->shouldReceive('dispatch')
->once()
->with(Mockery::type(Attempting::class));

$this->eventDispatcher->shouldReceive('dispatch')
->once()
->with(Mockery::type(Validated::class));

$this->assertTrue($this->guard->once($credentials));
}

Expand All @@ -367,6 +414,14 @@ public function it_should_attempt_to_authenticate_the_user_by_credentials_and_re
->with($user, $credentials)
->andReturn(false);

$this->eventDispatcher->shouldReceive('dispatch')
->once()
->with(Mockery::type(Attempting::class));

$this->eventDispatcher->shouldReceive('dispatch')
->once()
->with(Mockery::type(Failed::class));

$this->assertFalse($this->guard->once($credentials));
}

Expand Down
6 changes: 3 additions & 3 deletions tests/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -283,22 +283,22 @@ public function test_if_show_blacklisted_exception_configuration_is_enabled()
{
$this->manager->setBlackListExceptionEnabled(true);

$this->assertIsBool($this->manager->gettBlackListExceptionEnabled());
$this->assertIsBool($this->manager->getBlackListExceptionEnabled());
}

/** @test */
public function test_if_black_listed_exception_is_set_to_true()
{
$this->manager->setBlackListExceptionEnabled(true);

$this->assertTrue($this->manager->gettBlackListExceptionEnabled());
$this->assertTrue($this->manager->getBlackListExceptionEnabled());
}

/** @test */
public function test_if_black_listed_exception_is_set_to_false()
{
$this->manager->setBlackListExceptionEnabled(false);

$this->assertFalse($this->manager->gettBlackListExceptionEnabled());
$this->assertFalse($this->manager->getBlackListExceptionEnabled());
}
}

0 comments on commit 71ef3e6

Please sign in to comment.