* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Test; use Mockery; use Tymon\JWTAuth\Blacklist; use Tymon\JWTAuth\Claims\Collection; use Tymon\JWTAuth\Claims\Expiration; use Tymon\JWTAuth\Claims\IssuedAt; use Tymon\JWTAuth\Claims\Issuer; use Tymon\JWTAuth\Claims\JwtId; use Tymon\JWTAuth\Claims\NotBefore; use Tymon\JWTAuth\Claims\Subject; use Tymon\JWTAuth\Contracts\Providers\Storage; use Tymon\JWTAuth\Payload; use Tymon\JWTAuth\Validators\PayloadValidator; class BlacklistTest extends AbstractTestCase { /** * @var \Tymon\JWTAuth\Contracts\Providers\Storage|\Mockery\MockInterface */ protected $storage; /** * @var \Tymon\JWTAuth\Blacklist */ protected $blacklist; /** * @var \Mockery\MockInterface|\Tymon\JWTAuth\Validators\Validator */ protected $validator; public function setUp(): void { parent::setUp(); $this->storage = Mockery::mock(Storage::class); $this->blacklist = new Blacklist($this->storage); $this->validator = Mockery::mock(PayloadValidator::class); } /** @test */ public function it_should_add_a_valid_token_to_the_blacklist() { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp + 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foo'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator); $refreshTTL = 20161; $this->storage->shouldReceive('get') ->with('foo') ->once() ->andReturn([]); $this->storage->shouldReceive('add') ->with('foo', ['valid_until' => $this->testNowTimestamp], $refreshTTL + 1) ->once(); $this->blacklist->setRefreshTTL($refreshTTL)->add($payload); } /** @test */ public function it_should_add_a_token_with_no_exp_to_the_blacklist_forever() { $claims = [ new Subject(1), new Issuer('http://example.com'), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foo'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator); $this->storage->shouldReceive('forever')->with('foo', 'forever')->once(); $this->blacklist->add($payload); } /** @test */ public function it_should_return_true_when_adding_an_expired_token_to_the_blacklist() { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp - 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foo'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator, true); $refreshTTL = 20161; $this->storage->shouldReceive('get') ->with('foo') ->once() ->andReturn([]); $this->storage->shouldReceive('add') ->with('foo', ['valid_until' => $this->testNowTimestamp], $refreshTTL + 1) ->once(); $this->assertTrue($this->blacklist->setRefreshTTL($refreshTTL)->add($payload)); } /** @test */ public function it_should_return_true_early_when_adding_an_item_and_it_already_exists() { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp - 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foo'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator, true); $refreshTTL = 20161; $this->storage->shouldReceive('get') ->with('foo') ->once() ->andReturn(['valid_until' => $this->testNowTimestamp]); $this->storage->shouldReceive('add') ->with('foo', ['valid_until' => $this->testNowTimestamp], $refreshTTL + 1) ->never(); $this->assertTrue($this->blacklist->setRefreshTTL($refreshTTL)->add($payload)); } /** @test */ public function it_should_check_whether_a_token_has_been_blacklisted() { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp + 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foobar'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator); $this->storage->shouldReceive('get')->with('foobar')->once()->andReturn(['valid_until' => $this->testNowTimestamp]); $this->assertTrue($this->blacklist->has($payload)); } public function blacklist_provider() { return [ [null], [0], [''], [[]], [['valid_until' => strtotime('+1day')]], ]; } /** * @test * @dataProvider blacklist_provider * * @param mixed $result */ public function it_should_check_whether_a_token_has_not_been_blacklisted($result) { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp + 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foobar'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator); $this->storage->shouldReceive('get')->with('foobar')->once()->andReturn($result); $this->assertFalse($this->blacklist->has($payload)); } /** @test */ public function it_should_check_whether_a_token_has_been_blacklisted_forever() { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp + 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foobar'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator); $this->storage->shouldReceive('get')->with('foobar')->once()->andReturn('forever'); $this->assertTrue($this->blacklist->has($payload)); } /** @test */ public function it_should_check_whether_a_token_has_been_blacklisted_when_the_token_is_not_blacklisted() { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp + 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foobar'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator); $this->storage->shouldReceive('get')->with('foobar')->once()->andReturn(null); $this->assertFalse($this->blacklist->has($payload)); } /** @test */ public function it_should_remove_a_token_from_the_blacklist() { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp + 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foobar'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator); $this->storage->shouldReceive('destroy')->with('foobar')->andReturn(true); $this->assertTrue($this->blacklist->remove($payload)); } /** @test */ public function it_should_set_a_custom_unique_key_for_the_blacklist() { $claims = [ new Subject(1), new Issuer('http://example.com'), new Expiration($this->testNowTimestamp + 3600), new NotBefore($this->testNowTimestamp), new IssuedAt($this->testNowTimestamp), new JwtId('foobar'), ]; $collection = Collection::make($claims); $this->validator->shouldReceive('setRefreshFlow->check')->andReturn($collection); $payload = new Payload($collection, $this->validator); $this->storage->shouldReceive('get')->with(1)->once()->andReturn(['valid_until' => $this->testNowTimestamp]); $this->assertTrue($this->blacklist->setKey('sub')->has($payload)); $this->assertSame(1, $this->blacklist->getKey($payload)); } /** @test */ public function it_should_empty_the_blacklist() { $this->storage->shouldReceive('flush'); $this->assertTrue($this->blacklist->clear()); } /** @test */ public function it_should_set_and_get_the_blacklist_grace_period() { $this->assertInstanceOf(Blacklist::class, $this->blacklist->setGracePeriod(15)); $this->assertSame(15, $this->blacklist->getGracePeriod()); } /** @test */ public function it_should_set_and_get_the_blacklist_refresh_ttl() { $this->assertInstanceOf(Blacklist::class, $this->blacklist->setRefreshTTL(15)); $this->assertSame(15, $this->blacklist->getRefreshTTL()); } }