Search code examples
jqueryajaxlaravel-5.5

Laravel 5.5: 403 Forbidden when making AJAX POST


I've been stuck on this for 2 days now, and all the resolutions I looked for on StackOverflow and Laracasts proved inconclusive.

I am using Laravel 5.5 with jQuery and I do my testing in Firefox.

My AJAX GET calls are working fine, however, when I try and push an entry in my database, I get a 403 error.

My header does contain the CSRF token:

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

Models are created for every table called in my controller:

public function pushProfile(Request $request){
        $userid = \Auth::user()->id;
        $data = $request->message;
        $stat = \App\Character::where('owner', $userid)->first();
        $mess = \App\Message::firstOrCreate([
            'posterID' => $userid,
            'loc_x' => '0',
            'loc_y' => '0',
            'characterID' => $stat->id,
            'type' => 'profile'
        ]);
        $mess->content = $data;
        $mess->save();
        return response()->json(['success'=>'Message has been saved!']);
    }

Here is the AJAX call, it basically checks for my Quilljs Delta. This Deltais a JSON object formatting a message from WYSIWYG. Then every 5th second, it should try to push it to my database.

I know the Quilljs side works fine because my deltas show properly in my console. But the POST call itself doesn't seem to pass authentication for some reason? (This is just my guess, to me it seems like the only reason it would send a 403.)

setInterval(function() {
      if (change.length() > 0) {
        console.log('Saving changes', change);
        /* AJAX setup */
        $.ajaxSetup({
          headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
          }
        });
        $.ajax({
            headers: {
              'Content-Type':'application/json'
            },
            method: 'POST',
            url: '{{ url("/pushProfile") }}',
            data: {
              message:
              { 
                doc: JSON.stringify(quill.getContents())
              },
              _token: $('meta[name="csrf-token"]').attr('content')
            },
            dataType: 'JSON',
            error: function(jqXHR, textStatus, errorThrown) {
              console.log(JSON.stringify(jqXHR));
              console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
            },
            success: function (data) { 
                $(".writeinfo").append(data.msg); 
                console.log("Success!!!");
            }
        });
        change = new Delta();
      }
    }, 5*1000);

To make sure the issue didn't come from CSRF, I went a bit overkill and, after trying to set up the token first in ajaxSetup, then in the AJAX data only, I just assigned it in both. None of these scenarios changed anything.

Of course, I assigned the 'Web' middleware on my post route to check for the above-mentioned CSRF token. The route I use is as follows:

Route::group(['middleware' => ['web']], function () {
  Route::post('/pushProfile','MessageSend@pushProfile')->name('pushProfile');
});

I also tried to assign the URL as:

url: '/pushProfile',

To no avail, unfortunately... This just returns a 404 instead of the 403 I currently have:

{
"readyState":4,
"responseText":"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html>
    <head>\n<title>403 Forbidden</title>\n</head>
    <body>\n<h1>Forbidden</h1>\n
    <p>You don't have permission to access 
    /folder/public/{{ route(&quot;pushProfile&quot;) }}\n
    on this server.<br />\n</p>\n
    <hr>\n
    <address>Apache/2.4.35 (Win64) PHP/7.2.10 Server at localhost Port 80</address>\n
    </body>
    </html>\n",
"status":403,
"statusText":"Forbidden"
}

Did I miss anything? Thanks!


Solution

  • I found the solution, and oh god it was so simple I'm ashamed of myself:

    I was calling the AJAX from a .js file, using the blade route. Moving the call into a blade file solved the whole issue, as blade routes are only rendered in .blade.php files...

    I'm leaving the issue out there in case anyone stumbles upon the same trouble :)