-
Notifications
You must be signed in to change notification settings - Fork 784
[8.x] Add tests for getting the access token with the password grant #1181
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
<?php | ||
|
||
namespace Laravel\Passport\Tests\Feature; | ||
|
||
use Carbon\CarbonImmutable; | ||
use Illuminate\Contracts\Hashing\Hasher; | ||
use Illuminate\Database\Eloquent\Factory; | ||
use Illuminate\Database\Schema\Blueprint; | ||
use Illuminate\Support\Facades\Schema; | ||
use Laravel\Passport\Client; | ||
use Laravel\Passport\ClientRepository; | ||
use Laravel\Passport\HasApiTokens; | ||
use Laravel\Passport\Token; | ||
use Laravel\Passport\TokenRepository; | ||
use Lcobucci\JWT\Parser; | ||
|
||
class AccessTokenControllerTest extends PassportTestCase | ||
{ | ||
protected function setUp(): void | ||
{ | ||
parent::setUp(); | ||
|
||
Schema::create('users', function (Blueprint $table) { | ||
$table->increments('id'); | ||
$table->string('email')->unique(); | ||
$table->string('password'); | ||
$table->dateTime('created_at'); | ||
$table->dateTime('updated_at'); | ||
}); | ||
} | ||
|
||
protected function tearDown(): void | ||
{ | ||
Schema::dropIfExists('users'); | ||
|
||
parent::tearDown(); | ||
} | ||
|
||
protected function getUserClass(): ?string | ||
{ | ||
return User::class; | ||
} | ||
|
||
public function testGettingAccessTokenWithPasswordGrant() | ||
{ | ||
$this->withoutExceptionHandling(); | ||
|
||
$password = 'foobar123'; | ||
$user = new User(); | ||
$user->email = '[email protected]'; | ||
$user->password = $this->app->make(Hasher::class)->make($password); | ||
$user->save(); | ||
|
||
/** @var Client $client */ | ||
$client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); | ||
|
||
$response = $this->post( | ||
'/oauth/token', | ||
[ | ||
'grant_type' => 'password', | ||
'client_id' => $client->id, | ||
'client_secret' => $client->secret, | ||
'username' => $user->email, | ||
'password' => $password, | ||
] | ||
); | ||
|
||
$response->assertOk(); | ||
|
||
$response->assertHeader('pragma', 'no-cache'); | ||
$response->assertHeader('cache-control', 'no-store, private'); | ||
$response->assertHeader('content-type', 'application/json; charset=UTF-8'); | ||
|
||
$decodedResponse = $response->decodeResponseJson(); | ||
|
||
$this->assertArrayHasKey('token_type', $decodedResponse); | ||
$this->assertArrayHasKey('expires_in', $decodedResponse); | ||
$this->assertArrayHasKey('access_token', $decodedResponse); | ||
$this->assertArrayHasKey('refresh_token', $decodedResponse); | ||
$this->assertSame('Bearer', $decodedResponse['token_type']); | ||
$expiresInSeconds = 31622400; | ||
$this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @X-Coder264 this line was failing for us randomly. I had to update the value of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @driesvints This tests the expiration time of the issued access token. The expiration time for the password grant is being set here: https://github.com/laravel/passport/blob/v8.4.0/src/PassportServiceProvider.php#L116 This calls The difference between our numbers is 86400 seconds which is exactly one day. I guess there is some weird time related stuff going on with that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did the test maybe start to fail after 29.02.? If so then it is related to the leap year which is exactly why there was a one day difference between our expiration numbers 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hah, that could be yeah |
||
|
||
$jwtAccessToken = (new Parser())->parse($decodedResponse['access_token']); | ||
$this->assertTrue($this->app->make(ClientRepository::class)->findActive($jwtAccessToken->getClaim('aud'))->is($client)); | ||
$this->assertTrue($this->app->make('auth')->createUserProvider()->retrieveById($jwtAccessToken->getClaim('sub'))->is($user)); | ||
|
||
$token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->getClaim('jti')); | ||
$this->assertInstanceOf(Token::class, $token); | ||
$this->assertFalse($token->revoked); | ||
$this->assertTrue($token->user->is($user)); | ||
$this->assertTrue($token->client->is($client)); | ||
$this->assertNull($token->name); | ||
$this->assertLessThanOrEqual(5, CarbonImmutable::now()->addSeconds($expiresInSeconds)->diffInSeconds($token->expires_at)); | ||
} | ||
|
||
public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() | ||
{ | ||
$password = 'foobar123'; | ||
$user = new User(); | ||
$user->email = '[email protected]'; | ||
$user->password = $this->app->make(Hasher::class)->make($password); | ||
$user->save(); | ||
|
||
/** @var Client $client */ | ||
$client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); | ||
|
||
$response = $this->post( | ||
'/oauth/token', | ||
[ | ||
'grant_type' => 'password', | ||
'client_id' => $client->id, | ||
'client_secret' => $client->secret, | ||
'username' => $user->email, | ||
'password' => $password.'foo', | ||
] | ||
); | ||
|
||
$response->assertStatus(400); | ||
|
||
$response->assertHeader('cache-control', 'no-cache, private'); | ||
$response->assertHeader('content-type', 'application/json'); | ||
|
||
$decodedResponse = $response->decodeResponseJson(); | ||
|
||
$this->assertArrayNotHasKey('token_type', $decodedResponse); | ||
$this->assertArrayNotHasKey('expires_in', $decodedResponse); | ||
$this->assertArrayNotHasKey('access_token', $decodedResponse); | ||
$this->assertArrayNotHasKey('refresh_token', $decodedResponse); | ||
|
||
$this->assertArrayHasKey('error', $decodedResponse); | ||
$this->assertSame('invalid_grant', $decodedResponse['error']); | ||
$this->assertArrayHasKey('error_description', $decodedResponse); | ||
$this->assertArrayHasKey('hint', $decodedResponse); | ||
$this->assertArrayHasKey('message', $decodedResponse); | ||
|
||
$this->assertSame(0, Token::count()); | ||
} | ||
|
||
public function testGettingAccessTokenWithPasswordGrantWithInvalidClientSecret() | ||
{ | ||
$password = 'foobar123'; | ||
$user = new User(); | ||
$user->email = '[email protected]'; | ||
$user->password = $this->app->make(Hasher::class)->make($password); | ||
$user->save(); | ||
|
||
/** @var Client $client */ | ||
$client = $this->app->make(Factory::class)->of(Client::class)->state('password_client')->create(['user_id' => $user->id]); | ||
|
||
$response = $this->post( | ||
'/oauth/token', | ||
[ | ||
'grant_type' => 'password', | ||
'client_id' => $client->id, | ||
'client_secret' => $client->secret.'foo', | ||
'username' => $user->email, | ||
'password' => $password, | ||
] | ||
); | ||
|
||
$response->assertStatus(401); | ||
|
||
$response->assertHeader('cache-control', 'no-cache, private'); | ||
$response->assertHeader('content-type', 'application/json'); | ||
|
||
$decodedResponse = $response->decodeResponseJson(); | ||
|
||
$this->assertArrayNotHasKey('token_type', $decodedResponse); | ||
$this->assertArrayNotHasKey('expires_in', $decodedResponse); | ||
$this->assertArrayNotHasKey('access_token', $decodedResponse); | ||
$this->assertArrayNotHasKey('refresh_token', $decodedResponse); | ||
|
||
$this->assertArrayHasKey('error', $decodedResponse); | ||
$this->assertSame('invalid_client', $decodedResponse['error']); | ||
$this->assertArrayHasKey('error_description', $decodedResponse); | ||
$this->assertSame('Client authentication failed', $decodedResponse['error_description']); | ||
$this->assertArrayNotHasKey('hint', $decodedResponse); | ||
$this->assertArrayHasKey('message', $decodedResponse); | ||
$this->assertSame('Client authentication failed', $decodedResponse['message']); | ||
|
||
$this->assertSame(0, Token::count()); | ||
} | ||
} | ||
|
||
class User extends \Illuminate\Foundation\Auth\User | ||
{ | ||
use HasApiTokens; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.