Skip to content

Commit 9dd8e86

Browse files
authored
Merge pull request #18 from eschricker/feature/authentication-events
Migrated PR2137: Authentication events
2 parents d45c9da + b67704d commit 9dd8e86

File tree

3 files changed

+142
-8
lines changed

3 files changed

+142
-8
lines changed

src/JWTGuard.php

+84-6
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212
namespace PHPOpenSourceSaver\JWTAuth;
1313

1414
use BadMethodCallException;
15+
use Illuminate\Auth\Events\Attempting;
16+
use Illuminate\Auth\Events\Failed;
17+
use Illuminate\Auth\Events\Validated;
1518
use Illuminate\Auth\GuardHelpers;
1619
use Illuminate\Contracts\Auth\Guard;
1720
use Illuminate\Contracts\Auth\UserProvider;
21+
use Illuminate\Contracts\Events\Dispatcher;
1822
use Illuminate\Http\Request;
1923
use Illuminate\Support\Traits\Macroable;
2024
use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;
@@ -48,6 +52,20 @@ class JWTGuard implements Guard
4852
*/
4953
protected $request;
5054

55+
/**
56+
* The event dispatcher instance.
57+
*
58+
* @var \Illuminate\Contracts\Events\Dispatcher
59+
*/
60+
protected $events;
61+
62+
/**
63+
* The name of the Guard.
64+
*
65+
* @var string
66+
*/
67+
protected $name = 'tymon.jwt';
68+
5169
/**
5270
* Instantiate the class.
5371
*
@@ -57,11 +75,12 @@ class JWTGuard implements Guard
5775
*
5876
* @return void
5977
*/
60-
public function __construct(JWT $jwt, UserProvider $provider, Request $request)
78+
public function __construct(JWT $jwt, UserProvider $provider, Request $request, Dispatcher $eventDispatcher)
6179
{
6280
$this->jwt = $jwt;
6381
$this->provider = $provider;
6482
$this->request = $request;
83+
$this->events = $eventDispatcher;
6584
}
6685

6786
/**
@@ -75,7 +94,8 @@ public function user()
7594
return $this->user;
7695
}
7796

78-
if ($this->jwt->setRequest($this->request)->getToken() &&
97+
if (
98+
$this->jwt->setRequest($this->request)->getToken() &&
7999
($payload = $this->jwt->check(true)) &&
80100
$this->validateSubject()
81101
) {
@@ -92,7 +112,7 @@ public function user()
92112
*/
93113
public function userOrFail()
94114
{
95-
if (! $user = $this->user()) {
115+
if (!$user = $this->user()) {
96116
throw new UserNotDefinedException;
97117
}
98118

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

146+
$this->fireAttemptEvent($credentials);
147+
126148
if ($this->hasValidCredentials($user, $credentials)) {
127149
return $login ? $this->login($user) : true;
128150
}
129151

152+
$this->fireFailedEvent($user, $credentials);
153+
130154
return false;
131155
}
132156

@@ -387,7 +411,13 @@ public function getLastAttempted()
387411
*/
388412
protected function hasValidCredentials($user, $credentials)
389413
{
390-
return $user !== null && $this->provider->validateCredentials($user, $credentials);
414+
$validated = $user !== null && $this->provider->validateCredentials($user, $credentials);
415+
416+
if ($validated) {
417+
$this->fireValidatedEvent($user);
418+
}
419+
420+
return $validated;
391421
}
392422

393423
/**
@@ -399,7 +429,7 @@ protected function validateSubject()
399429
{
400430
// If the provider doesn't have the necessary method
401431
// to get the underlying model name then allow.
402-
if (! method_exists($this->provider, 'getModel')) {
432+
if (!method_exists($this->provider, 'getModel')) {
403433
return true;
404434
}
405435

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

422452
return $this->jwt;
423453
}
424454

455+
/**
456+
* Fire the attempt event.
457+
*
458+
* @param array $credentials
459+
*
460+
* @return void
461+
*/
462+
protected function fireAttemptEvent(array $credentials)
463+
{
464+
$this->events->dispatch(new Attempting(
465+
$this->name,
466+
$credentials,
467+
false
468+
));
469+
}
470+
471+
/**
472+
* Fires the validated event.
473+
*
474+
* @param \Illuminate\Contracts\Auth\Authenticatable $user
475+
*
476+
* @return void
477+
*/
478+
protected function fireValidatedEvent($user)
479+
{
480+
$this->events->dispatch(new Validated(
481+
$this->name,
482+
$user
483+
));
484+
}
485+
486+
/**
487+
* Fire the failed authentication attempt event.
488+
*
489+
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
490+
* @param array $credentials
491+
*
492+
* @return void
493+
*/
494+
protected function fireFailedEvent($user, array $credentials)
495+
{
496+
$this->events->dispatch(new Failed(
497+
$this->name,
498+
$user,
499+
$credentials
500+
));
501+
}
502+
425503
/**
426504
* Magically call the JWT instance.
427505
*

src/Providers/AbstractServiceProvider.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ protected function extendAuthGuard()
9595
$guard = new JWTGuard(
9696
$app['tymon.jwt'],
9797
$app['auth']->createUserProvider($config['provider']),
98-
$app['request']
98+
$app['request'],
99+
$app['events']
99100
);
100101

101102
$app->refresh('request', $guard, 'setRequest');

tests/JWTGuardTest.php

+56-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
namespace PHPOpenSourceSaver\JWTAuth\Test;
1313

1414
use Illuminate\Auth\EloquentUserProvider;
15+
use Illuminate\Auth\Events\Attempting;
16+
use Illuminate\Auth\Events\Failed;
17+
use Illuminate\Auth\Events\Validated;
18+
use Illuminate\Contracts\Events\Dispatcher;
1519
use Illuminate\Contracts\Auth\UserProvider;
1620
use Illuminate\Http\Request;
1721
use Mockery;
@@ -41,13 +45,24 @@ class JWTGuardTest extends AbstractTestCase
4145
*/
4246
protected $guard;
4347

48+
/**
49+
* @var \lluminate\Contracts\Events\Dispatcher|\Mockery\MockInterface
50+
*/
51+
protected $eventDispatcher;
52+
4453
public function setUp(): void
4554
{
4655
parent::setUp();
4756

4857
$this->jwt = Mockery::mock(JWT::class);
4958
$this->provider = Mockery::mock(EloquentUserProvider::class);
50-
$this->guard = new JWTGuard($this->jwt, $this->provider, Request::create('/foo', 'GET'));
59+
$this->eventDispatcher = Mockery::mock(Dispatcher::class);
60+
$this->guard = new JWTGuard(
61+
$this->jwt,
62+
$this->provider,
63+
Request::create('/foo', 'GET'),
64+
$this->eventDispatcher
65+
);
5166
}
5267

5368
/** @test */
@@ -206,6 +221,14 @@ public function it_should_return_a_token_if_credentials_are_ok_and_user_is_found
206221
->with(['foo' => 'bar'])
207222
->andReturnSelf();
208223

224+
$this->eventDispatcher->shouldReceive('dispatch')
225+
->once()
226+
->with(Mockery::type(Attempting::class));
227+
228+
$this->eventDispatcher->shouldReceive('dispatch')
229+
->once()
230+
->with(Mockery::type(Validated::class));
231+
209232
$token = $this->guard->claims(['foo' => 'bar'])->attempt($credentials);
210233

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

254+
$this->eventDispatcher->shouldReceive('dispatch')
255+
->twice()
256+
->with(Mockery::type(Attempting::class));
257+
258+
$this->eventDispatcher->shouldReceive('dispatch')
259+
->twice()
260+
->with(Mockery::type(Validated::class));
261+
231262
$this->assertTrue($this->guard->attempt($credentials, false)); // once
232263
$this->assertTrue($this->guard->validate($credentials)); // twice
233264
}
@@ -248,6 +279,14 @@ public function it_should_return_false_if_credentials_are_invalid()
248279
->with($user, $credentials)
249280
->andReturn(false);
250281

282+
$this->eventDispatcher->shouldReceive('dispatch')
283+
->once()
284+
->with(Mockery::type(Attempting::class));
285+
286+
$this->eventDispatcher->shouldReceive('dispatch')
287+
->once()
288+
->with(Mockery::type(Failed::class));
289+
251290
$this->assertFalse($this->guard->attempt($credentials));
252291
}
253292

@@ -348,6 +387,14 @@ public function it_should_authenticate_the_user_by_credentials_and_return_true_i
348387
->with($user, $credentials)
349388
->andReturn(true);
350389

390+
$this->eventDispatcher->shouldReceive('dispatch')
391+
->once()
392+
->with(Mockery::type(Attempting::class));
393+
394+
$this->eventDispatcher->shouldReceive('dispatch')
395+
->once()
396+
->with(Mockery::type(Validated::class));
397+
351398
$this->assertTrue($this->guard->once($credentials));
352399
}
353400

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

417+
$this->eventDispatcher->shouldReceive('dispatch')
418+
->once()
419+
->with(Mockery::type(Attempting::class));
420+
421+
$this->eventDispatcher->shouldReceive('dispatch')
422+
->once()
423+
->with(Mockery::type(Failed::class));
424+
370425
$this->assertFalse($this->guard->once($credentials));
371426
}
372427

0 commit comments

Comments
 (0)