8

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?

6
  • By default auth:api middleware requires each user to have a field in the database called api_token, did you add one? Commented May 5, 2018 at 20:01
  • That's not really the issue here. Passport created a field in the user table called remember_token and my API routes are all working properly with OAuth from my REST client. The issue is consuming those same API routes from the Vue.js / Axios front end I'm trying to build. Commented May 5, 2018 at 20:05
  • Ah, so you have the token in the frontend, but are not sure on how to attach it to the request? Commented May 5, 2018 at 20:10
  • I seem to have broken something now. I'm now only getting undefined back from Axios, even when I disable all auth. Notably, I see a 404 error in the console for /js/bootstrap.js.map. Searches for that issue bring back a million hits, but no working answers. Commented May 6, 2018 at 15:31
  • Okay, I fixed the thing that broke the whole script. I still get the 404 error int he console about /js/bootstrap.js.map, but that doesn't seem to matter because I get the desired result when I disable auth on the route. So I'm back to where I was when I first posted this question and still don't have a working solution. Commented May 6, 2018 at 23:35

3 Answers 3

12

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...

Sign up to request clarification or add additional context in comments.

2 Comments

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
8

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);
  });

Comments

4

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);
              });
        }
    }
}
  )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.