3
votes

I hope you're doing well. I'm struggling since several days with Laravel Passport, trying to consume my own api with javascript / vuejs. The last evenings were spend reading nearly every existing post about my problem, but I could not find any solution. I hope you can help me, thank you at this point.

I've set up a fresh laravel application and installed Laravel Passport like it its described in this offical doc for Laravel 5.8 (https://laravel.com/docs/5.8/passport#introduction). I've done every single point from the tutorial multiple times in different applications, without any success. To test my setup, I'm using this small axios request.

axios.get('/oauth/clients')
    .then(response => {
    console.log(response);
    }).catch(error => {
    console.log(response);
    })

When I'm logged in, its works fine, when I use a bearer token and use postman to test '/oauth/clients' it works also fine, but when I'm not logged in it always returns 401 Unauthenticated. My goal is to create an api, that I can consume from my own application as an unauthenticated user without a bearer token, but not from the outside. I thought Laravel Passport is the correct way to do this.

My request headers:

:authority: laravel.dev
:method: GET
:path: /oauth/clients
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
cache-control: no-cache
cookie: XSRF-TOKEN=eyJpdiI6IkxTTGs2cEtvbXc5cmhIZDhEV1lBXC9nPT0iLCJ2YWx1ZSI6IlpPcjdCbmlDcURraG03MndjUTVYeTV1WXl1YWx3MVdNWjFrZ1QrRENJcnlhZVVCNWtZdzl5VDN6ZjdkclBGK0siLCJtYWMiOiI3ZmQ4YjlkZmU3OWMyNjNiYWVhNzJhMWVkOGRhOGJhMzJkNWQwZmZjMDhmZDM2Y2IxYWRkODJiNzFhNmQ5NDA1In0%3D; laravel_session=eyJpdiI6IlpKc3EyS2R4NjAyM0t5XC8xaTR6SjJBPT0iLCJ2YWx1ZSI6Im1JRlRReVFHQ01jTlNQT3BkYlI1V0dNeE1BMkVvODhnWXNjM1VPRUFBRWRBRnl1N1diUmpOSkVJUmc0NTdsVFgiLCJtYWMiOiI0ZTZkNzE2OGQ5MzJkY2FmYzEzOWZiYjA3YTRiM2MxOGQ3OGJmNWIzMTI4ODA5MDMxYWVlMjJmOTk1M2FjZDdlIn0%3D
pragma: no-cache
referer: https://laravel.dev/
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
x-csrf-token: 4Opsva9oDk6LkAapLGqqh9AuPzWKfVH4PYoxcMB1
x-requested-with: XMLHttpRequest
x-xsrf-token: eyJpdiI6IkxTTGs2cEtvbXc5cmhIZDhEV1lBXC9nPT0iLCJ2YWx1ZSI6IlpPcjdCbmlDcURraG03MndjUTVYeTV1WXl1YWx3MVdNWjFrZ1QrRENJcnlhZVVCNWtZdzl5VDN6ZjdkclBGK0siLCJtYWMiOiI3ZmQ4YjlkZmU3OWMyNjNiYWVhNzJhMWVkOGRhOGJhMzJkNWQwZmZjMDhmZDM2Y2IxYWRkODJiNzFhNmQ5NDA1In0=

Response headers:

cache-control: no-cache, private
content-type: application/json
date: Sun, 07 Jul 2019 19:05:25 GMT
server: nginx/1.15.5
set-cookie: XSRF-TOKEN=eyJpdiI6IklTWEkrRTJxYXpiRFNQUm0zM3RLYWc9PSIsInZhbHVlIjoiMDEzSmVlMldQOXBrVUQxQjlCUGVVN2dpUk9VWmwrUlRjend3XC9CaUk1S2V6dUFlTDZtVWttREV5cVBPOFwveVQ0IiwibWFjIjoiZWZhMzA3OGVhYmY2NWNjNjgyMTg4NzAxZjQzNWYxZGQyMjVmMWY3MjAwNjllZTM5ODFiNjFiNWY1NGFjOGM0NiJ9; expires=Sun, 07-Jul-2019 21:05:25 GMT; Max-Age=7200; path=/
set-cookie: laravel_session=eyJpdiI6IlFLUDN0bGhBNW1UTytlbGgrcEZ0ekE9PSIsInZhbHVlIjoibHFvM09CSTFyZ05Kd0E0REVCekNOYmRocm01cnBVY3h1YjFOaXpyTXVcL05QSTNYdFFBdVpXZHd4NDVURGwralwvIiwibWFjIjoiYzM0ZWNhNzQ5MTJhY2VmNTZjZmM1YjFiNTgzYjU0NmZhZGIzZjVjYTFkOGNjYWEwNDEwODUyMzc5OWI2Njc3YiJ9; expires=Sun, 07-Jul-2019 21:05:25 GMT; Max-Age=7200; path=/; httponly
status: 401

Important note: I've shared the project with a friend of mine, he works on MacOs with Laravel in a docker container and the authorization works on his device without any changes. I'm running on a windows machine with Laravel Homestead. Could this problem be caused by Laravel Homestead or nginx?

2
Rewrite your api functions and frontened to handle 401 Unauthenticated... - Bart

2 Answers

3
votes

The route 'oauth/clients' is defined under the 'oauth' prefix (e.g., /oauth/any-route) using both the 'web' and 'auth' middlewares. This explains why you are receiving a 401 error when you are not logged in, as the 'auth' middleware is failing.

/vendor/laravel/passport/src/RouteRegistrar.php

 /**
 * Register the routes needed for managing clients.
 *
 * @return void
 */
public function forClients()
{
    $this->router->group(['middleware' => ['web', 'auth']], function ($router) {
        $router->get('/clients', [
            'uses' => 'ClientController@forUser',
            'as' => 'passport.clients.index',
        ]);

        ...
    });
}

Also, you should not be using 'web' middleware for your API routes. The API is stateless and should not receive or respond with any session data. This means no need for CSRF/XSRF tokens, which I can see are being transmitted in your example.

You need to place your API routes within the specified API routes file. You'll notice that the authorization middleware 'auth:api' is also slightly different for API routes.

/routes/api.php

Route::middleware(['auth:api'])->group(function () {
    Route::get('/your/path', 'Api\YourController@index');
});

Then in Postman, simply pass your bearer token and expected response type. And don't forget to add the 'api' prefix to your route, as you will do for all routes within the api.php routes file.

/api/your/path

Authorization   Bearer {your_token}
Accept          application/json

Hope this helps and good luck!

0
votes

Thank you for your answer @matticustard. I've written a small controller to test the authorization and put the route in the following groupe with auth:api middleware:

Route::group(['prefix' => 'v1', 'middleware' => 'auth:api', 'namespace' => 'Api\v1', 'as' => 'api.'], function () {});

When I use a bearer token and postman it works fine, but I want to use this route also from my application as an user who is not logged in. But only from my application not from the outside, how can I achieve this?

axios.get('/api/v1/test')
    .then(response => {
    console.log(response);
    }).catch(error => {
    console.log(response);
    })

Thank you for your time :)