I have a Laravel 8 website in which users fill in a form and click a link to take them to an external payment website. Once the user has paid (or canceled payment), the payment website redirects the user to my site. For about 30% of users, the browser cookie storing the laravel_session cookie is not included in the headers and the user is logged out of my website. According to Apache logs, The browser/platform is not a consistent factor in whether the user's cookie disappears or not.
The payment site is calling my url with HTTPS. HTTPS is forced on by Apache config, so I am sure that all users are starting off from the same domain they are being returned to. Perhaps the only smidgen of doubt I have is that some users are using an old URL that redirects to the new URL using an .htaccess directive. When I go to the old URL, I see the new URL in the browser's address bar, matching the redirect address in the payment site, so I do think that is all working normally.
When the user submits the form, it brings them to a controller method that does this:
public function saveForm(Request $request) {
<snip>
$temp = call_user_func([new $controllerClass, $function], $request);
$sessionCookie = Cookie::get(config('session.cookie'));
logger()->info('Session Cookie Value: ' . $sessionCookie); //always returns a proper value
return $temp;
}
Note that I am not calling a route here, and no route is defined for $function, so I don't expect any middleware to kick on the call to $function.
The $function in question makes a curl call to the payment website for a token. Upon success, I log the session value again for debugging, and redirect like this. Note that I am not making any changes to the cookie before redirecting. :
$sessionCookie = Cookie::get(config('session.cookie'));
logger()->info('Session Cookie Value: ' . $sessionCookie); //always returns a proper value
return redirect()->away($url);
I am returning up the chain without using die or dd or anything that would kill execution.
I believe my middleware is pretty out-of-the-box:
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,
\App\Http\Middleware\SetLocale::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
protected $routeMiddleware = [
'auth' => \App\Http\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,
];
My route for receiving the redirection from the payment site is under 'web':
Route::post('pay/accepted', [PayController::class, 'accepted'])->name('pay.accepted');
Session.php values:
'driver' => env('SESSION_DRIVER', 'file'),
'lifetime' => 120,
'expire_on_close' => true,
'encrypt' => false,
'files' => storage_path('framework/sessions'),
'connection' => null,
'table' => 'sessions',
'lottery' => [2, 100],
'cookie' => 'laravel_session',
'path' => '/',
'domain' => null,
'secure' => env('SESSION_SECURE_COOKIE', null),
When the payment site redirects to mine, the first indication that something is wrong is that EncryptCookies::handle does not see a cookie in the headers. Inside Authenticate::handle, Auth::check() is false and the user is redirected to auth/login. Again, this only happens about 30% of the time, making it difficult to debug properly.
I'd be very grateful for any ideas on how to debug further.