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

E+E's avatar
Level 3

301 Redirect to /login after posting with AJAX even though I'm logged in.

Hey all, I setup a admin route group in RouteServiceProvider.php with web middleware group and auth middleware:

protected function mapAdminRoutes()
{
        Route::prefix('admin')
            ->middleware(['web', 'auth'])
            ->namespace($this->namespace.'\Admin')
            ->group(base_path('routes/admin.php'));
}
        

Here's what my app/Http/Kernel.php looks like:

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 = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \Barryvdh\Cors\HandleCors::class,
        \Frenzy\Turbolinks\Middleware\StackTurbolinks::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,
        ],
    ];

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

I have this route registered in routes/admin.php:

Route::post('/poems/update-order', 'PoemController@updateOrder');

I'm posting to this route client-side when I'm already logged in like so:

fetch('/admin/poems/update-order', {
      method: 'POST',
      body: JSON.stringify({
            order: order                
      }),
      headers: {                
            'Content-Type': 'application/json',
            'X-CSRF-TOKEN': window.Laravel.csrfToken
      }
})

And I'm getting a 302 redirect to /login. I've done a bunch of reading on this and it seems like the app should be picking up the user from session. For what it's worth, I've tried to use both file and cookie session drivers with the same result. I've tried a bunch of different things but the only thing that seems to work is removing the auth middleware. However, I need this to ensure the user is logged in when making the request. Anyone else run into this? I'm currently on Laravel v5.5.39.

Also, just to verify, here's what the route looks like when I list routes:

| | POST | admin/poems/update-order | | App\Http\Controllers\Admin\PoemController@updateOrder | web,auth |

I've seen this thread referenced a lot:

https://laravel.io/forum/02-09-2016-52-ajax-auth-not-picking-up-session

But, as you can see, I'm not using an api middleware group or anything, so I don't think I'm missing any middleware.

0 likes
10 replies
tykus's avatar

Set the Accept header to application/json

1 like
Cronix's avatar

Are you sure window.Laravel.csrfToken is returning the token?

E+E's avatar
Level 3

Yes, I believe so. Here are the request headers from the network tab of chrome dev tools:

Accept: application/json
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,la;q=0.8,lb;q=0.7
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 21
Content-Type: application/json
Host: thread.test
Origin: http://thread.test
Pragma: no-cache
Referer: http://thread.test/admin/poems
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
X-CSRF-TOKEN: iyaRnxj1flwm7jvWxSMvovm55wh6igdC1tc2IzlZ

Notice the X-CSRF-TOKEN header. Seems like that's correct.

Cronix's avatar

Try this

  1. logout
  2. delete all files from /storage/framework/sessions (except .gitignore!)
  3. login
  4. check dir from #2 to see if a session was generated (it should)
  5. make ajax request
  6. check dir from #2 to see if a 2nd session was generated (it shouldn't)
1 like
E+E's avatar
Level 3

Hmmmm. So yeah a 2nd session is being created with no user info in it.

tykus's avatar

Is the laravel_session cookie being sent? Are you in cross-domain situation?

1 like
E+E's avatar
Level 3

It doesn't look like there's any cookie header on my request (see above). I am seeing a 'Set-cookie' header in the response. My request url is relative (see above), so I'm thinking the cross-domain thing shouldn't be an issue?

Cronix's avatar

In addition to what @tykus said, is your APP_URL set correctly in config/.env? Are you using anything except the default session values in /config/session.php?

Check the cookies being sent in your browser dev tools. Is the domain correct?

1 like
E+E's avatar
E+E
OP
Best Answer
Level 3

Hey guys, thanks so much for your help. Definitely pointed me in the right direction.

The issue was that the Cookie header was not being sent in my request.

After doing some more digging, figured out that when using fetch, you have to explicitly set the credentials option in order for the Cookie header to be automatically set in the request. Weird.

https://github.com/github/fetch#sending-cookies

I probably should just stick with axios haha. Have had a bunch of weird issues with fetch.

Anyway, here's my updated code for anyone with the same issue:

fetch('/admin/poems/update-order', {
    method: 'POST',
    body: JSON.stringify({
        order: order                
    }),
    headers: {                
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': window.Laravel.csrfToken,
    },
    credentials: 'same-origin'
}))

Notice I was able to remove the Accept header.

Please or to participate in this conversation.