Home > database >  SPA Vue on Laravel post method not allowed. Setting csrf token?
SPA Vue on Laravel post method not allowed. Setting csrf token?

Time:11-27

I know this question is everywhere. But most of them are using blade and the rest of them have not being useful. I have tried in many ways to set this csrf-token but is not working. I'm trying to make an SPA with laravel API and the vuejs included in laravel 8. No matter what I keep getting "The POST method is not supported for this route. Supported methods: GET, HEAD."

This is my route on the route.api file is:

Route::post('api/authenticate', [LoginController::class, 'authenticate']);

I'm including a UsersService.js file where I'm planning to define all the api calls in functions in order to call them from the necessary components. So I have here the axios call.

import axios from 'axios'
export default {
  authenticate (formData) {
    return axios.post('api/authenticate', { formData })
  }
}

The only thing I have clear is that I need the token and in order to be sure that is there I have added a script on the layout blade file where I load my components like this. So I can access the token with AppSettings.csrfToken

<script>
  window.AppSettings = {
    csrfToken: "{{ csrf_token() }}"
  }
</script>

And this is my component

<template>
    <div class="text-center">
        <div class="form-signin" style="width: 100%; max-width: 330px; padding: 15px; margin: 0 auto;">
                <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
                <label for="inputEmail" class="sr-only">Email address</label>
                <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required="" autofocus="" v-model="formData.email">
                <label for="inputPassword" class="sr-only">Password</label>
                <input type="password" id="inputPassword" class="form-control" placeholder="Password" required="" v-model="formData.password">
                <div class="checkbox mb-3">
                    <label>
                    <input type="checkbox" value="remember-me"> Remember me
                    </label>
                </div>
                <button class="btn btn-lg btn-primary btn-block" @click="login">Sign in</button>
                <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
        </div>
    </div>
</template>

<script>
    import UsersService from '../../services/UsersService.js'
    export default {
        data(){
          return{
                formData: {
                    email: '',
                    password: '',
                    deviceName: 'browser',
                    _token: AppSettings.csrfToken
                }
            }
        },
        async created () {
        },
       methods:{
           async login(){
                const res = await UsersService.authenticate(this.formData)
                console.log(res)
           },
        }
    }
</script>

cors.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure your settings for cross-origin resource sharing
    | or "CORS". This determines what cross-origin operations may execute
    | in web browsers. You are free to adjust these settings as needed.
    |
    | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    |
    */

    'paths' => [
        'api/*',
        'sanctum/csrf-cookie'
    ],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

];

I have the token, right there, I can read it, what should I do with it, in which way must be set on the axios in order to allow this POST request.

Following the sanctum guid in laravel's website I have also added axios.defaults.withCredentials = true; but it does nothing. Also like this answer CSRF token using SPA

return axios.post('api/authenticate', { formData, _token: AppSettings.csrfToken })

But that also didn't work, for sure I'm not understanding something or I'm looking in the wrong place. I've ran out of ideas, any help here?

CodePudding user response:

You probably got sidetracked bcs CSRF is a common problem, but the error does not mention CSRF, and the problem has nothing to do with CSRF. The error tells you there is something wrong with your routing.

From the docs:

Routes defined in the routes/api.php file are nested within a route group by the RouteServiceProvider. Within this group, the /api URI prefix is automatically applied so you do not need to manually apply it to every route in the file.

The route you have in routes/api.php is:

Route::post('api/authenticate', [LoginController::class, 'authenticate']);

So because that is automatically prefixed with /api, it actually defines the route /api/api/authenticate. Your Axios code POSTs to /api/authenticate, but that has no associated route.

  • Related