Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

raidboss's avatar

[API] Post request returns 419 with React's axios but 200 with Postman

Hi there, Kinda of a newbie to laravel and API development. But here's the issue:

I have a route that logs a user in using Sanctum authentication like so:

public function login(Request $request){

        $fields = $request->validate([
           'email' => 'required',
           'password' => 'required'
        ]);

        //Check user
        $user = User::where('email', $fields['email'])->first();

        if(!$user || !Hash::check($fields['password'], $user->password)){
            return response([
                'message' => 'Bad credentials'
            ], 401);
        }

        $token = $user->createToken('userauthtoken')->plainTextToken;

        $response = [
            'user' => $user,
            'token' => $token
        ];

        return response($response, 201);
    }

In the Postman app, it works perfectly. I get a JSON object with the user information and the access token. But when I try to make a post request using Axios in React like so:

const postData = async () => {
    axios.post('/login', {
      email : '[email protected]',
      password : '321'
    })
    .then(res => console.log(res));
  }

My cors.php file looks like this:

<?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,

];

And in my session.php config file, the cookie domain name points to an env. field that does not exist in the env file (SESSION_DOMAIN). I found this a bit odd.

 'domain' => env('SESSION_DOMAIN', null),

It returns a 419 error. Please keep in mind that this route is not protected.

From what I've read, I need to implement CSRF in my post request, but how do I go about doing this? Should I make a GET end point that returns the csrf_token() and stores it in localStorage? And then pass it somehow in the headers?

Any help is appreciated.

Thank you for reading my post

0 likes
27 replies
uniksk's avatar

419 is page expired error. It is due to the csrf_token() issue.

One solution could be as you said to make a GET route to make get a csrf_token() and use that later. But it will be a big security issue which csrf_token() is preventing.

Csrf is there to prevent your application from Cross-Site Request Forgery Attack. If you are making a public get route to get the csrf token, which everyone can request to and get the token, then what's the use of csrf_token(). Everyone will be able to call the get route to get the token and make a POST request to your website and exploit.

1 like
raidboss's avatar

How can I implement the CSRF token in another way? I understand that doing it by the GET request is a security flaw, but how should I do it then?

shoemoney's avatar

You can just use a private static key like a md5 hash of your email or something as a bandaid. For dev env it should be fine. For production tho your gonna need to figure that out.

This is what i was just going to do but in doing it I figured it out cause i saw how its generated.

I suggest improving your github foo and looking at others code.

If I was a react person id paste you some code... but im not a dork. I kid...

apex1's avatar

You need to call sanctum/csrf-cookie route before calling login. axios will set the token automatically

1 like
raidboss's avatar

Can you point me to some documentation or tutorial? Laravel docs don't really cover this I don't think.

raidboss's avatar
According to the laravel's documentation, I must first define an endpoint that returns the XSRF token and only after that I may submit any forms (login, signup etc). Is this the best approach?
martinbean's avatar

@raidboss Why are you using Sanctum, but then not using Sanctum properly and instead return plain text tokens in a HTTP response?

If this is for a SPA, then follow the instructions on using Sanctum for a SPA instead of trying to roll your own and weakening how secure your app is, because if you’re returning a plain text token then I’m assuming you’re storing a plain text token. And if you’re then authentication with plain text tokens then you just may as well not bother.

1 like
raidboss's avatar

I followed Traversy Media's Sanctum tutorial. This is not a SPA as I intend to make the API available for react-native aswell.

I am not securing the token anywhere client side yet, that is the problem haha I am not sure how to do that

raidboss's avatar

Also, I need to be able to set the CRFS token and I am also not sure how to do that. If you could point me in the right direction that would be appreactiated

martinbean's avatar

@raidboss You don’t need CSRF protected for native mobile app authentication. Read the official docs I linked you to above, and not some randomer’s tutorial.

raidboss's avatar

The problem is my end points http error 419 which is associated with the CSRF token

martinbean's avatar

@raidboss Only web routes have CSRF protection by default. So if you’re getting 419 responses, move your API routes to the routes/api.php file, where they should be any way.

raidboss's avatar

I am using api.php but I'm accessing it using React. My vision is to use it in React native in the future though. This is just a project for learning BTW

martinbean's avatar

@raidboss Again, you will only get 419 (CSRF token expired) if:

  1. The route you’re POST-ing to is actually in your web routes file and not the API routes file.
  2. You have, for some reason, also added the VerifyCsrfToken middleware to your API routes. Which you shouldn’t have.
1 like
raidboss's avatar

I am getting 419 (unknown status).

I have not added anything, everything is as is by default.

Should I not do CSRF in an API? Many posts say otherwise.

What is your hourly rate to fix and teach me how to solve this problem?

raidboss's avatar

Also, how would you know that the route I am posting to is in my web routes? obvious it's not since im metioning an API lol. Obviously it's in the routes/api routes and I'm getting the responses from http://localhost:8000/api/users for example. I have no idea how you can assume stuff like that.

apex1's avatar

Can you show your middlewares in kernel file?

raidboss's avatar
<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Fruitcake\Cors\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
}

Yorhmzy's avatar

@raidboss Uncomment the first element in the api array.

// Uncomment this line
// You don't need it when you are authenticating a mobile app
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
1 like
uniksk's avatar

Look at this video by Traversy Media on Laravel 8 REST API With Sanctum Authentication.

TimeStamp you are looking at:

  1. 39:05 - Register User & Get Token
  2. 45:30 - Logout & Delete Token
  3. 48:00 - Login User & Get Token
1 like
raidboss's avatar

Yes I followed that tutorial previously but I feel like he doesn't cover how to deal with the tokens client side. Also, there is no CRSF tokens in his API which is missing from mine aswell.

raidboss's avatar

I can not login to get the sanctum token without the crsf token and Brad does not cover that

chomreun's avatar

change url from localhost:3000 to 127.0.0.1:3000. the url which request to frontend on your browser

5 likes

Please or to participate in this conversation.