Secure your Laravel routes with signed URLs

Secure your Laravel routes with signed URLs

When building web applications, ensuring the security of certain routes is crucial, especially when dealing with sensitive operations like email confirmations, password resets, or unsubscribing from a service. Laravel provides a robust way to secure routes using signed URLs. Signed URLs add a cryptographic signature to the URL, ensuring that the URL has not been tampered with.

Understanding signed URLs

Signed URLs include a hash signature generated using a secret key. This signature ensures the URL's integrity, meaning it has not been altered since it was generated. If someone tries to modify the URL, the signature becomes invalid, and Laravel will reject the request.

Basic Usage

Here’s a basic example to illustrate how to generate a signed URL in Laravel:

use Illuminate\Support\Facades\URL;

$url = URL::signedRoute('unsubscribe', ['user' => 1]);

In this example, the signedRoute method generates a signed URL for the unsubscribe route, including the user ID as a parameter.

Real-Life Example

Consider a scenario where you need to send an email to users with a link to unsubscribe from a newsletter. Here’s how you can implement this using signed URLs:

  1. Define the route in your web.php file:
use App\Http\Controllers\NewsletterController;

Route::get('/unsubscribe/{user}', [NewsletterController::class, 'unsubscribe'])->name('unsubscribe')->middleware('signed');

The middleware('signed') ensures that only requests with a valid signature can access this route.

  1. Generate the signed URL in your controller:
use Illuminate\Support\Facades\URL;
use App\Models\User;

class NewsletterController extends Controller
{
    public function sendUnsubscribeLink(User $user)
    {
        $url = URL::signedRoute('unsubscribe', ['user' => $user->id]);

        // Send the URL in an email
        Mail::to($user->email)->send(new UnsubscribeMail($url));
    }

    public function unsubscribe(User $user)
    {
        // Unsubscribe logic here
        return 'You have been unsubscribed!';
    }
}
  1. Send the signed URL in an email:
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class UnsubscribeMail extends Mailable
{
    use Queueable, SerializesModels;

    public $url;

    public function __construct($url)
    {
        $this->url = $url;
    }

    public function build()
    {
        return $this->view('emails.unsubscribe')
                    ->with(['url' => $this->url]);
    }
}
  1. Create the email view (resources/views/emails/unsubscribe.blade.php):
<!DOCTYPE html>
<html>
<head>
    <title>Unsubscribe</title>
</head>
<body>
    <p>If you wish to unsubscribe from our newsletter, please click the link below:</p>
    <a href="{{ $url }}">Unsubscribe</a>
</body>
</html>

In this example, a signed URL is generated and sent to the user via email. When the user clicks the link, Laravel verifies the signature before allowing access to the unsubscribe method.

Pro Tip

Use temporarySignedRoute to generate signed URLs that expire after a specified time:

$url = URL::temporarySignedRoute('unsubscribe', now()->addMinutes(30), ['user' => 1]);

This adds an additional layer of security by ensuring that the URL can only be used within a certain timeframe.

Conclusion

Signed URLs in Laravel provide a secure way to protect routes and ensure that only legitimate requests can access sensitive operations. By leveraging this feature, you can enhance the security of your application and provide a safer user experience. Implement signed URLs in your Laravel projects to take advantage of this powerful security feature.

If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!

Subscribe to Harris Raftopoulos

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe