Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Roni's avatar
Level 33

Passport for Local API Requests

I'm starting a web app that looks like it could that it might be a really good use case for an actual app. Normally when working on web sites or apps that wont be served by making an actual app, when using vue components, I'd just use really basic token encryption. In some earlier work I've had them call routes in web.php directly.

However, in this project it's likely that after its running for a month or two the request will come to transition it to an app. That being said, is passport the right place to start to api authentication? Let me clarify a use case, it's medical app for use only by staff for patients.

In an example vue component, there may be a search for medical history or previous lists of treatment, physicians or anything, I can't really look at it the same way I would look at picking products from a vendor, so I'm assuming regular token auth is off the table. I could be wrong if someone knows more I'd appreciate the reasoning. What I'm looking for is a way for the Vue component to get that information from api endpoints, and still be secure.

When I say API endpoints, there is no CORS happening it's all in the same app. I'll also need to add/update records from vue equally secure. There won't be any public access to this information, no external registration. Only staff will be able to log in and access the data. There won't be any logging in using facebook / github / google etc...

So the main purpose of the ultra secured API is for the website vue components for now, (or in the future possibly an app) to communicate with the data layer.

Am I over thinking this? Is basic token authentication enough, is JWT or passport the right solution? Can anyone point to the best way to accomplish this setup. Oddly I've found laracasts pretty lacking in this area, and most tutorials focus on the CORS aspect without actually touching on simple API security.

Thanks in advance for any advice.

0 likes
2 replies
tobischulz's avatar

If you will use your api later with an mobile app you should use passport. With OAuth2 in passport you can revoke any accesstoken if required, with jwt you cant.

I use passport the same way with a vuejs frontend in the same laravel project. Take a look at how to use passport with javascript: https://laravel.com/docs/6.0/passport#consuming-your-api-with-javascript

I think this should help you out.

Later on different apps you can use all the grant types passport oauth2 offers.

Cheers

Roni's avatar
Level 33

Thanks @belv3dere,

I'm trying to process this all, it's one of those issues that is so easy that it's in fact hard. If you or someone could look at my failing test to and let me know what, I could do to make it pass, it would be really helpful.

So, I have a clean install of laravel 6.0

I've installed passport as follows:

composer require laravel/passport
php artisan migrate
php artisan passport:install

php artisan make:auth

I've added HasApiTokens to User.php and Passport::routes();to AuthServiceProvider.php, I've also changed my config/auth.php to use passport for token authentication and finally added \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, to kernel.php in the web middleware section. So for my use case it looks like I'm set up.

Now here are the tests and everything passes except one, which is holding me back from moving forward.

<?php

namespace Tests\Feature;

use App\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Artisan;
use Laravel\Passport\Passport;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
    
    
    
    /** @test */
    public function it_has_oauth_clients_set_up() {
        
        $this->assertEquals(0, \DB::table('oauth_clients')->count());
        
        Artisan::call('passport:install');
        
        $this->assertEquals(2, \DB::table('oauth_clients')->count());
    }
    
    /** @test */
    public function non_protected_api_routes_are_accessible() {
        $this->getJson('api/ping')
            ->assertOk();
    }
    
    /** @test */
    public function secured_api_routes_are_are_not_accessible() {
        $this->getJson('api/secure/ping')
            ->assertUnauthorized();
    }

    /** @test */
    public function secure_api_route_can_be_accessed_by_authorized_users() {
        $user = factory(User::class)->create();
        Passport::actingAs($user);
        $this->getJson('api/secure/ping')
            ->assertOK();
    }
    
    /** @test */ //THIS IS THE TEST THAT FAILS
    public function test_actual_passport_implementation_of_user_hitting_api() {
        Artisan::call('passport:install');
        $user = factory(User::class)->create();
        $this->post('/login',[
            'email' => $user->email,
            'password' => 'password',
        ])

        //this assertion works, the user IS logged in and redirected.
            ->assertRedirect(route('home'));

    //however the middleware is NOT assigning a token to the user,
    // so I'm not sure how this is supposed to work!
    // The passport fake does work in the test above.
        
    dump(auth()->user()->token()); //should be something but it's null
    // unless I'm misunderstanding 
    // \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class
    // should be adding a token to the user session after each request
    }
    
}

Just in case someone wanted the api.php

Route::get('ping',function() {
    return response(['pong'=>'ok']);
});

Route::prefix('secure')->middleware('auth:api')->group(function(){
    Route::get('ping',function() {
        return response(['pong'=>'ok']);
    });
});

Any advice welcome. What am I missing on that last test?

Please or to participate in this conversation.