How to authenticate Vue.js / Axios request of an API route in Laravel

17,915

Solution 1

I solved it! I'm a bit embarrassed because the answer was actually in the Laravel docs, but I will say I tried this before posting the question here and it wasn't working. Perhaps something else was broken at the time.

Per the Laravel docs:

All you need to do is 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,
],

This Passport middleware will attach a laravel_token cookie to your outgoing responses. This cookie contains an encrypted JWT that Passport will use to authenticate API requests from your JavaScript application. Now, you may make requests to your application's API without explicitly passing an access token...

Solution 2

You will probably want to use Larvel Passport or a JWT auth mechanism for obtain the Authorization token.

Seeing as how you're using axios, add a request interceptor to attach the access token to every request once you successfully authenticate. A simple example:

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // assume your access token is stored in local storage 
    // (it should really be somewhere more secure but I digress for simplicity)
    let token = localStorage.getItem('access_token')
    if (token) {
       config.headers['Authorization'] = `Bearer ${token}`
    }
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

Solution 3

to use the auth:api first you need api_token inside your users table

Schema::table('users', function ($table) {
    $table->string('api_token', 80)->after('password')
                        ->unique()
                        ->nullable()
                        ->default(null);
});

also you can create a user for testing as follows

User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
        'api_token' => Str::random(60),
    ]);

in your layout use the following before @yield('content')

<script>
     window.Laravel = <?php echo json_encode(['api_token' => (Auth::user())->api_token]); ?>
</script>

now you can use window.laravel.api_token inside your vue js to use it in headers

heres an example

var methods = new Vue({
    el: '#tabs_lists',
    data: {
        config: {
            headers: {
              Authorization: 'Bearer ' + window.Laravel.api_token,
              Accept: 'application/json'
            }
           },
        data: []
    },
    methods: {
        test: function (link) {
            axios.get(link, this.config)
               .then(response => (this.data = response.data)).catch(function (error) {
                // handle error
                console.log(error);
              });
        }
    }
}
  )
Share:
17,915
jreikes
Author by

jreikes

Updated on July 29, 2022

Comments

  • jreikes
    jreikes almost 2 years

    I'm in Laravel 5.6. I have all my API routes built out and properly responding to requests from my REST client (Paw). I'm trying to build a simple front end to access those routes.

    I'm trying to use Laravel's out-of-the-box features as much as possible, so I'm using Axios to call those routes from a blade template using Vue.js. It works if I disable auth middleware on the test route, but I get 401 errors on the console when auth middleware is enabled for the route.

    The problem seems obvious enough... The auth:api guard on my /api routes wants to see an oauth token in the header, but when I log in with the web page it does session authentication. I assume there's a simple way to resolve this without having to spoof an oauth token request in the web frontend, right? Do I need to somehow pass the session token in my request with Axios? And, if so, do I also need to change the auth:api guard in my api routes file?

  • Tom Knapen
    Tom Knapen over 5 years
    In addition to this, I also had to call Passport::withoutCookieSerialization() from within my AppServiceProviders boot method. More information can be found in these Laravel upgrade notes
  • Kwaadpepper
    Kwaadpepper over 3 years