Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass laravel CSRF token value to vue

I have this form where the user should only type text inside a text area:

            <form action="#" v-on:submit="postStatus">{{-- Name of the method in Vue.js --}}
                <div class="form-group">
                    <textarea class="form-control" rows="5" maxlength="140" autofocus placeholder="What are you upto?" required v-model="post"></textarea>
                </div>
                <input type="submit" value="Post" class="form-control btn btn-info">

                {{ csrf_field() }}

            </form>

Then, I have this script code where I am using vue.js with ajax in order to pass that text into a controller and eventually save it into the database:

//when we actually submit the form, we want to catch the action
    new Vue({
        el      : '#timeline',
        data    :   {
            post    : '',
        },
        http    :   {
            headers: {
                'X-CSRF-Token': $('meta[name=_token]').attr('content')
            }
        },
        methods : {
            postStatus : function (e) {
                e.preventDefault();
                console.log('Posted: '+this.post+ '. Token: '+this.token);
                $.ajax({
                    url         :   '/posts',
                    type        :   'post',
                    dataType    :   'json',
                    data        :   {
                        'body'  :   this.post,
                    }
                });
            }
        },
    });

However, this doesn't work so far, since there's this token mismatch exception. I don't know how to make it work. How to pass this token value to the controller. I have tried the following:

1) inside the form, I have added a vue name to the token:

<input type="hidden" name="_token" value="YzXAnwBñC7qPK9kg7MGGIUzznEOCi2dTnG9h9çpB" v-model="token">

2) I have tried to pass this token value into the vue:

//when we actually submit the form, we want to catch the action
    new Vue({
        el      : '#timeline',
        data    :   {
            post    : '',
            token   : '',
        },
        methods : {
            postStatus : function (e) {
                e.preventDefault();
                console.log('Posted: '+this.post+ '. Token: '+this.token);
                $.ajax({
                    url         :   '/posts',
                    type        :   'post',
                    dataType    :   'json',
                    data        :   {
                        'body'  :   this.post,
                        '_token':   this.token,
                    }
                });
            }
        },
    });

... but in the console, vue doesn't even catch it :(

This leads me to the following error:

TokenMismatchException in VerifyCsrfToken.php line 68:

How do I fix it? Any ideas?

like image 276
Pathros Avatar asked Oct 08 '16 23:10

Pathros


People also ask

How CSRF token is implement in Laravel?

You can conveniently build JavaScript driven applications using JavaScript HTTP library, as this includes CSRF token to every outgoing request. The file namely resources/assets/js/bootstrap. js registers all the tokens for Laravel applications and includes meta tag which stores csrf-token with Axios HTTP library.

What is the use of {{ Csrf_field () }} In Laravel?

csrf_field(): This function can be used to generate the hidden input field in the HTML form. Note: This function should be written inside double curly braces. csrf_token(): This function just gives a random string. This function does not generate the hidden input field.


4 Answers

Very Easy Solution Just add a hidden field inside the form. An Example

<form id="logout-form" action="/logout" method="POST" style="display: none;">
    <input type="hidden" name="_token" :value="csrf">
</form>

Now add csrf variable inside script at the vue file, like this. (Remember, it must be inside data).

<script>
     export default {
        data: () => ({
            csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
          }),        
    }
</script>

N.B. You will see a meta tag in your blade.php file like this.

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

If there is nothing like this, you need to place it there.

like image 96
Md. Harun Or Rashid Avatar answered Oct 16 '22 21:10

Md. Harun Or Rashid


A better way is simply to pass the csrf token via a slot into the vue component.

In blade.php file:

@extends('layouts.app')

@section('content')
          <my-vue-component>
            {{ csrf_field() }}
          </my-vue-component>
@endsection

In MyVueComponent.vue

   <form role="form">
       <slot>
         <!-- CSRF gets injected into this slot -->
       </slot> 
       <!-- form fields here -->
    </form>
like image 34
lukio3 Avatar answered Oct 16 '22 20:10

lukio3


My solution to this is that all vue components get csrf token right before a request is made. I put this in my bootstrap.js file.

Vue.http.interceptors.push((request, next) => {
   request.headers.set('X-CSRF-TOKEN', CoolApp.csrfToken);
   next();
});

Then have a class CoolApp.php

    public function getScriptVariables()
    {
      return json_encode([
          'csrfToken' => csrf_token(),
      ]);
    }
like image 3
Marcus Avatar answered Oct 16 '22 22:10

Marcus


I solved it thanks to these two answers:

1) First I read this one, which led me to

2) This second one.

So, in my form I keep this:

{{ csrf_field() }}

And inside the js file I only add the following (outside and above the Vue instance):

var csrf_token = $('meta[name="csrf-token"]').attr('content');

So the whole js code is:

var csrf_token = $('meta[name="csrf-token"]').attr('content');
    /*Event handling within vue*/
    //when we actually submit the form, we want to catch the action
    new Vue({
        el      : '#timeline',
        data    :   {
            post    : '',
            token   : csrf_token,
        },
        methods : {
            postStatus : function (e) {
                e.preventDefault();
                console.log('Posted: '+this.post+ '. Token: '+this.token);
                $.ajax({
                    url         :   '/posts',
                    type        :   'post',
                    dataType    :   'json',
                    data        :   {
                        'body'  :   this.post,
                        '_token':   this.token,
                    }
                });
            }
        },
    });
like image 3
Pathros Avatar answered Oct 16 '22 22:10

Pathros