How to Create a Laravel URL Temporary Signed Route to an External URL
Tien Ho
Posted on August 30, 2024
In Laravel, signed URLs are a powerful way to ensure the integrity of routes by adding a signature that validates the URL. However, Laravel’s native signed routes feature is generally used for internal routes. What if you want to create a temporary signed route that redirects to an external URL? This article will guide you through the process.
Understand Laravel's Signed Routes
Laravel's signed URLs are typically used to generate links that point to a specific route within your application. These URLs carry a unique signature, which Laravel can validate to ensure that the URL has not been tampered with.
use Illuminate\Support\Facades\URL;
URL::temporarySignedRoute('name.route', now()->addMinutes(30), ['parameter' => $value]);
The code snippet above generates a URL that is valid for 30 minutes and includes a signature that ensures its validity.
Create a Signed Route for an External URL
This class is derived from the Illuminate\Routing\UrlGenerator
.
<?php
namespace App\Helpers;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\InteractsWithTime;
use Illuminate\Support\Arr;
class CustomSignedUrl
{
use InteractsWithTime;
public function customSignedUrl($baseUrl, $parameters = [], $expiration = null, $absolute = true)
{
$this->ensureSignedRouteParametersAreNotReserved(
$parameters = Arr::wrap($parameters)
);
if ($expiration) {
$parameters = $parameters + ['expires' => $this->availableAt($expiration)];
}
ksort($parameters);
$key = env("APP_FRONT_KEY");
$rt = $baseUrl ."?expires={$parameters['expires']}";
$parameters['signature'] = hash_hmac('sha256', $rt, $key);
return $baseUrl ."?expires={$parameters['expires']}&signature={$parameters['signature']}";
}
/**
* Ensure the given signed route parameters are not reserved.
*
* @param mixed $parameters
* @return void
*/
protected function ensureSignedRouteParametersAreNotReserved($parameters)
{
if (array_key_exists('signature', $parameters)) {
throw new \Exception(
'"Signature" is a reserved parameter when generating signed routes. Please rename your route parameter.'
);
}
if (array_key_exists('expires', $parameters)) {
throw new \Exception(
'"Expires" is a reserved parameter when generating signed routes. Please rename your route parameter.'
);
}
}
}
Use the Signed External URL
Assume we have two domains: one for the admin side and one for the front page. We want to create a front page user from the admin side and send an email verification.
This's code for custom send verify email.
<?php
namespace App\Mail;
use App\Helpers\CustomSignedUrl;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\InteractsWithTime;
class CustomVerifyEmail extends VerifyEmail
{
use InteractsWithTime;
protected function verificationUrl($notifiable)
{
if (static::$createUrlCallback) {
return call_user_func(static::$createUrlCallback, $notifiable);
}
$sha1 = sha1($notifiable->email);
$id = $notifiable->getKey();
$baseUrl = env('APP_FRONT_URL')."app/verify-email/{$id}/{$sha1}";
$signedUrl = (new CustomSignedUrl())->customSignedUrl($baseUrl, [
'id' => $id,
'hash' => $sha1
],
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60))
);
return $signedUrl;
}
}
Front User model:
...
public function sendEmailVerificationNotification()
{
$this->notify(new CustomVerifyEmail);
}
Posted on August 30, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.