I am trying to create a Feature test that tests getting an OAuth access token. When using Postman, everything works great (actual code) so I am confident it is in my test code I am not implementing the setup correctly.
In the past, I have run the artisan command, and simply copy/paste the client_secret
into my .env
file. Because I am using CI/CD, I cannot do that. I need to either:
- create an artisan command to append the
.env
- read the secret from the
oauth_clients
table (seems the easiest route)
I've followed this SO thread to help get where I'm at, but not able to make it work.
Here is what my test looks like:
MyFeatureTest.php
use RefreshDatabase, WithFaker, DatabaseMigrations;
public function setUp(): void
{
parent::setUp();
$this->artisan('passport:install');
}
public function a_user_can_get_a_token()
{
$credentials = [
'username' => 'username',
'password' => 'password',
];
$http = $this->postJson('api/v1/login', $credentials);
$response = json_decode($http->getContent());
// dd($response);
$http->assertStatus(200)
->assertJsonStructure([
'token_type', 'expires_in', 'access_token', 'refresh_token',
])
->assertJson([
'token_type' => $response->token_type,
'expires_in' => $response->expires_in,
'access_token' => $response->access_token,
'refresh_token' => $response->refresh_token,
]);
In my Controller that handles the login
route:
public function __construct()
{
$this->client = DB::table('oauth_clients')
->where('id', 2)
->first();
}
...
public function getOauthAccessToken($credentials)
{
$response = Http::asForm()->post(env('APP_URL') . '/oauth/token', [
'grant_type' => 'password',
'client_id' => $this->client->id,
'client_secret' => $this->client->secret,
'username' => $credentials['username'],
'password' => $credentials['password'],
'scope' => '*',
]);
if ($response->successful()) {
return $response->json();
} else {
dd($response->body());
}
}
When using postman to test my routes/controller, everything works great. I get a Barer token back as expected.
When I run my Feature test, my controller returns null
.
Trying to troubleshoot, I've tried dd($response->body())
above. Here is what I am getting:
"{"error":"invalid_client","error_description":"Client authentication failed","message":"Client authentication failed"}"
If I dd($this->client->secret)
, I am able to see the key. This is super confusing as it looks like everything is working...
How can I properly set up my test so that passport is ready to go/configured when I hit the login test(s)? Thank you for any suggestions!