ahoi's avatar
Level 5

Test Passport-Login

Hello everybody,

I'd like to write a test that checks whether a user is able to log in using the LoginController's method.

This is the controller's method:

 public function login(Request $request)
    {
        $this->validate($request, $this->rules(),
            $this->validationErrorMessages());

        $request = Request::create('/oauth/token', 'POST', [
            'grant_type'    => 'password',
            'client_id'     => config('services.vue_client.id'),
            'client_secret' => config('services.vue_client.secret'),
            'username'      => $request->email,
            'password'      => $request->secret,
        ]);

        return app()->handle($request);
    }

Now this is my test:

public function test_user_can_log_in_via_api(){

    $user = User::factory()->create([
        'password' => 'secret',
    ]);

    $body = [
        'email' => $user->email,
        'secret' => 'secret',
    ];

    $this->json('POST','/api/auth/login',$body,['Accept' => 'application/json'])
    ->assertStatus(200)->assertJsonStructure(['token_type','expires_in','access_token','refresh_token']);
}

I guess this is the case because I am using a testing-database and this database does not know anything about the "productive" client_id and client_secret.

How would you solve this issue?

0 likes
6 replies
martinbean's avatar

@ahoi You wouldn’t test this… because you’re using Passport completely wrong.

What is app()->handle($request) all about?

Passport is an OAuth server implementation. So either use an appropriate OAuth grant type where you don’t expose your client’s secret key, or use Sanctum instead which is literally built for authentication things like Vue front-ends.

If you wish to stick with Passport, then the most appropriate grant type would be authorization code grant with PKCE:

The Authorization Code grant with "Proof Key for Code Exchange" (PKCE) is a secure way to authenticate single page applications or native applications to access your API.

ahoi's avatar
Level 5

Hi,

can you tell me why I am using Passport wrong?

Laravel is used in combination with Vue and the app is also providing OAUTH for other web apps.

martinbean's avatar
Level 80

Because you’re meant to get OAuth tokens from your OAuth endpoints; not proxy calls with a web controller.

Laravel is used in combination with Vue and the app is also providing OAUTH for other web apps.

That’s what multiple OAuth clients are for. Create a client for your web app, and also individual clients for the other web apps. The clients then identify themselves using the client ID so you know which client issued a particular access token.

1 like
ahoi's avatar
Level 5

Alright, I understand.

So I'd create a new client using php artisan passport:client --public

➜  myapp git:(V4) ✗ sail artisan passport:client --public

 Which user ID should the client be assigned to?:
 > 1

 What should we name the client?:
 > pkce

 Where should we redirect the request after authorization? [http://myapp.test/auth/callback]:
 > 

New client created successfully.
Client ID: 4
Client secret: 

So my last question about this: Are there good examples out there how to implement this in my Laravel-app? If I understood you correctly, I should not get the token from my controller - but how would I get them?

Would be great if you'd be able to get me some information, docs, examples because all examples I found are somehow handling and returning the token within the controller...

Please or to participate in this conversation.