ycs77/laravel-recover-session

Recover Laravel session when form post back from third-party API.

Fund package maintenance!
Patreon

v1.2.0 2023-06-20 09:48 UTC

This package is auto-updated.

Last update: 2024-12-12 12:13:24 UTC


README

Latest Version on Packagist Software License GitHub Tests Action Status Style CI Build Status Total Downloads

Recover Laravel session when sending a form post request back from a third-party API like NewebPay.

Currently, Laravel's default Cookie SameSite value is set to Lax. This setting prevents cookies from being sent when using form post requests to transmit data to websites on other domains. Consequently, after completing a payment and being redirected back to the original website, users may appear to be automatically logged out due to the inability to retrieve the original login cookie. This package addresses and resolves this issue.

Installation

Via Composer:

composer require ycs77/laravel-recover-session

Publish config:

php artisan vendor:publish --tag=recover-session-config

Usage

Now you need to call RecoverSession::preserve() to save the current session ID into the cache and include the key in your callback URL. This allows the current session to be resumed after the API returns with the key:

use Ycs77\LaravelRecoverSession\Facades\RecoverSession;

public function pay(Request $request)
{
    $key = RecoverSession::preserve($request);

    ThirdPartyApi::callbackUrl('/pay/callback?sid='.$key);

    // send post form request to the third-party API...
}

This package will automatically retrieve the encrypted session ID from the callback URL and restore the original session state upon returning to the site.

Reference details for the SameSite: https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure

Manually Register Middleware

If you are not using the global recover session, you can set the config recover-session.global to false, and adjust the order of the middleware so that RecoverSession is placed below StartSession. by default, Laravel's Kernel does not include the $middlewarePriority property, so you need to add it manually.

If you are using Laravel 9 or 10, you should add the $middlewarePriority property in your application's app/Http/Kernel.php file:

class Kernel extends HttpKernel
{
    /**
     * The priority-sorted list of middleware.
     *
     * Forces non-global middleware to always be in the given order.
     *
     * @var string[]
     */
    protected $middlewarePriority = [
        \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
        \Illuminate\Cookie\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Ycs77\LaravelRecoverSession\Middleware\RecoverSession::class, // need to place `RecoverSession` below `StartSession`
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class,
        \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
        \Illuminate\Contracts\Session\Middleware\AuthenticatesSessions::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];
}

If you are using Laravel 11+, you can add the RecoverSession middleware to the $middlewarePriority property in the app/Http/Kernel.php file:

->withMiddleware(function (Middleware $middleware) {
    $middleware->priority([
        \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
        \Illuminate\Cookie\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Ycs77\LaravelRecoverSession\Middleware\RecoverSession::class, // need to place `RecoverSession` below `StartSession`
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
        \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class,
        \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ]);
})

If you are using Laravel 11.31+, it provides a concise method to append middleware to the priority list:

->withMiddleware(function (Middleware $middleware) {
    $middleware->appendToPriorityList(
        \Ycs77\LaravelRecoverSession\Middleware\RecoverSession::class,
        \Illuminate\Routing\Middleware\ValidateSignature::class
    );
})

Final, you can add the RecoverSession middleware to the callback route for the API:

use Ycs77\LaravelRecoverSession\Middleware\RecoverSession;

Route::post('/pay/callback', [PaymentController::class, 'callback'])
    ->middleware(RecoverSession::class);

Sponsor

If you think this package has helped you, please consider Becoming a sponsor to support my work~ and your avatar will be visible on my major projects.

Become a Patron

Credits

License

MIT LICENSE