How to consume an authenticated API with Axios

Viewed 3380

I'm trying to build an application using Vue and Laravel. I currently use passport authentication within Laravel for user authentication. However, when I try to make a post request from a vue component using axio, I get 401 unauthorized, even if I am currently logged in.

Here is some example code:

1. Get request from the vue component

    getEvents() {
      axios
        .get("/api/calendar")
        .then(resp => (this.events = resp.data.data))
        .catch(err => console.log(err.response.data));
    }

2. Laravel routes

Route::apiResource('/calendar', 'CalendarController')->middleware('auth:api');

3. Calendar controller associated with the get request above

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return CalendarResource::collection(Calendar::all());
    }

I've spent hours with this issue and everything I have found simply doesn't work. So any help at all is extremely appeciated.

edit:

Extra details

I am using Laravel 5.8.35.

In regards to passport, I am using this documentation laravel.com/docs/5.8/passport and followed the installationm front end quick start and deploying steps.

second edit:

Full code on github

Here is the full project on github incase this can help. https://github.com/CMHayden/akal.app/tree/feature/Calendar

5 Answers

I made some changes to your project, here is the github repository https://github.com/AzafoCossa/ProFix, hope it works.

Open AuthServiceProvider.php file, add Passport::routes() to boot() function and open auth.php file, update 'api' guard from 'driver'=>'token' to 'driver'=>'passport' and finally open Kernel.php file, add this middleware:

'web' => [
   // Other middleware...
   \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],

Please confirm if you've set the meta value for csrf token in the entry html or blade file

<meta name="csrf-token" content="{{ csrf_token() }}">

Also the header for axios in the bootstrap.js file like this

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

Try adding the correct middleware along with the other suggestions here

'web' => [
    // Other middleware...
    \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],

https://laravel.com/docs/5.8/passport#consuming-your-api-with-javascript

Also you shouldn't need these lines that you have in the bootstrap or calendar component. Passport will take care of that for you with http only cookies.

//send Authorization token with each request
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;

All I did to the same problem is:

  1. in User.php, added on head,
'use Laravel\Passport\HasApiTokens;'

then inside the class, added

'HasApiTokens' to the line 'use Notifiable, HasRoles, HasApiTokens;'
  1. In config>auth.php , changed 'driver'=>'token' to 'driver'=>'passport' under 'api' under 'guard'.
'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
            'hash' => false,
        ],
    ],
  1. add the CreateFreshApiToken middleware to your web middleware group in your app/Http/Kernel.php file:
'web' => [
    // Other middleware...
    \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],

Nothing else. My axios request was: axios.get('api/cities');

It worked as I wanted. Only component can access the data. But no authenticated or unauthenticated user can access the data through direct url.

If you are storing auth token in cookie then you can do as follows

let token = cookie.get("token");
//send Authorization token with each request
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
axios
     .get("/api/calendar")
     .then(resp => console.log(resp.data))
     .catch(err => console.log(err))
Related