clarkewing / handoff
Lightweight Laravel package for secure cross-application user handoff via signed URLs and route mapping.
Requires
- php: ^8.0
- illuminate/auth: ^8.0|^9.0|^10.0|^11.0|^12.0
- illuminate/routing: ^8.0|^9.0|^10.0|^11.0|^12.0
- illuminate/support: ^8.0|^9.0|^10.0|^11.0|^12.0
- spatie/url: ^2.4
Requires (Dev)
- laravel/pint: ^1.5
- orchestra/testbench: ^6.0|^7.0|^8.0|^9.0|^10.0
- pestphp/pest: ^v1.23.1|^2.34|^3.7
- pestphp/pest-plugin-laravel: ^1.1|^2.3|^3.1
- pestphp/pest-plugin-type-coverage: ^3.6
- phpstan/phpstan: ^2.1
This package is auto-updated.
Last update: 2025-08-02 19:32:37 UTC
README
Handoff is a Laravel package that enables seamless, secure cross-application authentication via temporary signed URLs. Itโs ideal for projects maintaining both a legacy and a modern Laravel app, and ensures users can be automatically logged in across both systems without friction.
๐ Features
- ๐ Secure authentication handoff via signed URLs
- ๐ Bi-directional route mapping between apps
- โฑ๏ธ Expirable links with configurable TTL
- โ๏ธ Fully customizable user model & identifier
- ๐ Shared, environment-agnostic logic โ install on both apps
๐งฉ Requirements
To use Handoff, the package must be installed in both Laravel applications you wish to link and their User models must be kept in sync.
Handoff is compatible with applications using Laravel 8 and above, and requires PHP 8.0 or above.
๐ฆ Installation
Handoff must be installed in both your origin app and the target app.
composer require clarkewing/handoff
In your origin appโs .env
file, register the target host:
HANDOFF_TARGET_HOST="https://new.example.org"
โ๏ธ Configuration
Optionally, you can publish the config file using the following command.
php artisan vendor:publish --tag=handoff-config
Note: This is required if you want to use route mapping (see the Usage section).
These are the contents of the published config file:
/* |-------------------------------------------------------------------------- | Authentication |-------------------------------------------------------------------------- | | These settings control how authentication is handled when transferring | a user session from one site to another using a signed URL. | */ 'auth' => [ // The Authenticable model used in your application. 'model' => App\Models\User::class, /** @phpstan-ignore class.notFound */ // Lifetime (in seconds) of the signed URL used for authentication. // This helps ensure links expire quickly and remain secure. 'ttl' => env('HANDOFF_TTL', 300), ], /* |-------------------------------------------------------------------------- | Target Host |-------------------------------------------------------------------------- | | The base URL of the other application (legacy or new) that you want to | redirect users to. This will be prepended to any path in the route map. | */ 'target_host' => env('HANDOFF_TARGET_HOST', ''), /* |-------------------------------------------------------------------------- | Route Mapping |-------------------------------------------------------------------------- | | This defines which local named routes should redirect to which path on | the other site. Keys should match local route names, and values should | be relative paths on the remote app. You may repeat values if multiple | routes on this side map to a single target path. | */ 'routes' => [ // 'dashboard' => '/home', // 'settings.profile' => '/account/info', ],
๐ง Usage
Target app
In the target app, Handoff automatically registers a /handoff
endpoint via its service provider. This endpoint validates the signed URL, logs the user in, and redirects them to the intended destination.
Origin app
From the origin app, Handoff provides three ways of handing off a request to the target application:
- Manually generating a signed Handoff URL
- Automatically redirecting users via the
handoff
middleware and providing a target path - Automatically redirecting users via the
handoff
middleware while using route mapping
Manually generating a signed Handoff URL
Handoff supplies a GenerateHandoffUrl
action class which can be used to manually create a Handoff URL.
use App\Models\User; use ClarkeWing\Handoff\Actions\GenerateHandoffUrl; $url = resolve(GenerateHandoffUrl::class)->generate( user: $user, // required โ the user to authenticate toPath: '/account/info', // optional if using fromRoute fromRoute: 'settings.profile', // optional if using toPath ttl: 300 // optional โ expiration in seconds );
Note: Either toPath
or fromRoute
must be provided, not both.
Automatically redirecting users via the handoff
middleware and providing a target path
To simplify redirecting users, Handoff registers its handoff
middleware. It accepts a target path to which users will be redirected.
Route::get('/settings/profile', fn () => view('settings.profile')) ->middleware('handoff:/account/info')
Automatically redirecting users via the handoff
middleware while using route mapping
For cases where youโd prefer to centrally manage your handoff origin routes and target paths, Handoff provides the possibility to use route to path mapping.
1. Apply the handoff
middleware to origin routes
You have a few options for this. See the Laravel documentation on Registering Middleware.
2. Setup route mapping in the config
After publishing Handoffโs config file, you can set up route mapping:
// config/handoff.php 'routes' => [ 'dashboard' => '/home', 'settings.profile' => '/account/info', ],
๐ Security
This package uses Laravelโs temporarySignedRoute()
mechanism. URLs are cryptographically signed and valid only for a limited time. You can customize the TTL or add rate limiting via the included service provider.
๐ค Contributing
Issues and PRs welcome! Please see our Contribution guidelines if contributing tests or features.
๐ License
Released under the MIT License.