Laravel ShareLink: Secure Temporary Share Links for Your Laravel Applications

Introduction

Building secure, temporary sharing capabilities—be it for files, routes, model previews, or API endpoints—is essential in many Laravel projects. Laravel ShareLink, created by Grazulex, offers a comprehensive suite to centralize issuance, expiration, revocation, and analytics of share links with a clean facade-driven API.

In this article, you'll discover:

  • Installation & configuration

  • Generating secure share links with various constraints

  • Handling files, routes, and model previews

  • Monitoring, revocation, and security best practices

  • Useful CLI and event-driven workflows


Installation & Setup

Ensure you're using Laravel 11.x or 12.x and PHP 8.3+.

composer require grazulex/laravel-sharelink

Publish configuration, routes, optionally assets:

php artisan vendor:publish --provider="Grazulex\\ShareLink\\ShareLinkServiceProvider"

Configure aspects like expiration, rate limits, storage, etc., in config/sharelink.php.


The API is fluent and expressive. Here's an overview of all available options when generating a share link.

use ShareLink;

$link = ShareLink::create('my-link-key')

    // What is being shared
    ->forFile(storage_path('app/private/document.pdf'))        // Share a file (absolute path or Storage)
    // OR
    ->forRoute('preview.post', ['post' => 123])                // Share a named route
    // OR
    ->forUrl('https://example.com/custom/target')              // Share a raw URL
    // OR
    ->forModel($user)                                          // Share a model with default preview route
    // OR
    ->forText('Secret message to show once')                   // Share inline content directly

    // Security & Access Controls
    ->expiresAfter(now()->addDays(2))                          // Expiration date/time
    ->limitClicks(5)                                           // Max number of accesses
    ->burnAfterAccess()                                        // Auto-delete after first use
    ->withPassword('secret123')                                // Password-protected access (bcrypt)

    // Access Restrictions
    ->allowOncePerIp()                                         // One click per IP (prevents sharing)
    ->restrictToIp('123.45.67.89')                             // Only this IP can access
    ->restrictToIps(['1.1.1.1', '2.2.2.2'])                    // IP allowlist
    ->signed(true)                                             // Enforce Laravel signed route protection
    ->viaMiddleware(['auth', 'verified'])                      // Middleware protection (for route links)
    ->throttle('5,1')                                          // Throttle using Laravel format (5 hits/min)

    // Metadata (Optional)
    ->label('Quarterly Report')                                // Internal label
    ->description('Shared with the finance team')              // Optional description
    ->notifyOnAccess(true)                                     // Fire event or notification on access

    // Generation
    ->generate();                                              // Finalizes and persists the link

Once generated, the $link contains useful accessors:

$link->token;       // Only the token
$link->url();       // Full usable URL
$link->route();     // Internal route for Laravel use

Use Cases Illustrated

  • Private File Sharing: Send private or time-sensitive files to external collaborators.

  • Preview Unpublished Routes: Allow stakeholders to preview drafts or restricted routes.

  • API or JSON Model Previews: Offer public or temporary access to JSON resources.

  • One-Time Secrets: Burn-after-read access to confidential content.

  • Self-Destructing Links: Use .burnAfterAccess() for expiring tokens after use.


You can inspect, list, and revoke share links easily:

CLI Commands

php artisan sharelink:list              # List all active links
php artisan sharelink:revoke TOKEN     # Revoke a specific token
php artisan sharelink:clean            # Cleanup expired tokens

In Code

ShareLink::revoke($token);
ShareLink::find($token)->isExpired();

Events Fired

All major lifecycle events are available for logging or notifications:

  • ShareLinkCreated

  • ShareLinkAccessed

  • ShareLinkRevoked

  • ShareLinkExpired

You can attach listeners to alert users, store access logs, or revoke early.


Advanced Scenarios

You can group assets:

$link = ShareLink::create('multi-file')
    ->forFiles([
        storage_path('a.pdf'),
        storage_path('b.pdf'),
    ])
    ->zipOnAccess() // Bundle before download
    ->generate();

Dynamic Model Resolver

When sharing models, a custom resolver can define how the route and display should behave.

ShareLink::resolverFor(\App\Models\User::class, function ($model) {
    return route('admin.preview.user', ['id' => $model->id]);
});

Visualization

Here’s a diagram of the internal process:

graph TD
    A[Create Link] --> B[Store Token & Metadata]
    B --> C[Access Handler Middleware]
    C --> D[Throttle/IP Checks]
    D --> E{Password Required?}
    E -- Yes --> F[Prompt for Password]
    E -- No --> G[Render or Redirect]
    F --> G
    G --> H[Track Access & Fire Events]

You can hook into any of those steps via Laravel events, middleware, or overrideable service bindings.


Conclusion

Laravel ShareLink is a battle-ready solution for sharing routes, models, files, and secrets with precision control. It abstracts common patterns like signed routes, file streaming, expiration, and throttling into one unified API and CLI system.

Start integrating secure temporary links into your app today, and offer a premium experience with minimal effort.

🔗 GitHub: https://github.com/grazulex/laravel-sharelink
📘
Wiki: https://github.com/grazulex/laravel-sharelink/wiki

0
Subscribe to my newsletter

Read articles from Jean-Marc Strauven directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jean-Marc Strauven
Jean-Marc Strauven

Jean-Marc (aka Grazulex) is a developer with over 30 years of experience, driven by a passion for learning and exploring new technologies. While PHP is his daily companion, he also enjoys diving into Python, Perl, and even Rust when the mood strikes. Jean-Marc thrives on curiosity, code, and the occasional semicolon. Always eager to evolve, he blends decades of experience with a constant hunger for innovation.