Search code examples
ajaxlaravellaravel-5vue.jsvue-resource

Vue-Resource gives TokenMismatchException in Ajax POST call


Please note, I'm using the Laravel framework. Also please note, there are similar questions on SO, I've checked them, but wasn't able to solve my problem based on those solutions...

Even though I set my CSRF token right to my knowledge, I'm not sure why it won't work.

When checking the console, it seems I have 3 cookies: two Request cookies of which one is called XSRF-TOKEN and one is called laravel_session. And one respone laravel_session cookie. All have a different value!!!

My Vue:

new Vue({
    el:'body',
    http: {
        root: '/root',
        headers: {
            'X-CSRF-Token': $('meta[name=_token]').attr('content')
        }
    },  
});

My head:

<meta name="_token" content="{!! csrf_token() !!}"/>

My Vue component addNew method:

Vue.component('things',{
    template:'#things-panel-template',
    data(){
        return {
            list: [],
            newThing: {
                body: '',
                // _token: $('meta[name=_token]').attr('content'),
                // tried removing token from head meta and adding up here.
            },
        }
    },
    methods:{
        addNew(){
            var thing = this.newThing; // get input
            this.newThing = {body:''}; // clear input
            this.$http.post('/api/things/add',thing) // send
        },
    },
});

My route:

Route::post('/api/things/add',function(){
    return App\Thing::create(Request::get());
});

And finally, the form in my Vue Template:

<form action="/things/add"
        method="POST"
        @submit.prevent="addNew"
    >
        <div class="form-group">
            {{ csrf_field() }}
            <label for="">Add</label>
            <input type="text"
                name="body"
                id="task-body"
                class="form-control"
                v-model="newThing.body"
            >
            <button :disabled="!isValid"
                class="btn btn-primary"
                type="submit"
            >Add</button>
        </div>
    </form>

Solution

  • I found the answer myself:

    If you're gonna work with a vue-component, you should just add the token to that component instead. Otherwise it won't go with your ajax request. So put this part underneath the template in the component:

        http: {
            root: '/root',
            headers: {
                'X-CSRF-Token': $('meta[name=_token]').attr('content')
            }
        },  
    

    Do this to check if your token was properly sent inside the headers:

    1. Go to google chrome, open dev-tools, go to the network tab and Reload.
    2. Make the ajax call and look at the file added in the network tab, open it and go to the 'Headers' tab.
    3. Look at the bottom where it says: 'Request Headers' and check if the token was properly added in the request.