Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Uri Signer Laravel Package

code4nix/uri-signer

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require code4nix/uri-signer
    

    Ensure your Laravel project uses Symfony’s HttpFoundation (already included in Laravel via illuminate/http).

  2. Service Registration: Add the service to Laravel’s container in config/app.php under providers:

    Code4Nix\UriSigner\UriSignerBundle::class,
    

    Publish the config (if needed) via:

    php artisan vendor:publish --provider="Code4Nix\UriSigner\UriSignerBundle"
    
  3. First Use Case: Sign a URL in a controller:

    use Code4Nix\UriSigner\UriSigner;
    
    public function generateSignedUrl(UriSigner $uriSigner)
    {
        $unsignedUrl = url('download/file.pdf');
        $signedUrl = $uriSigner->sign($unsignedUrl, 3600); // Expires in 1 hour
        return response()->json(['url' => $signedUrl]);
    }
    

Implementation Patterns

Core Workflows

  1. Signing URLs:

    • Use sign() for one-off URL generation (e.g., download links, API endpoints).
    • Pass a custom expiration (in seconds) as the second argument:
      $uriSigner->sign('https://example.com/file', 900); // 15 minutes
      
    • Default expiration is 1 day (86400 seconds).
  2. Validation:

    • Manual URI Check:
      $isValid = $uriSigner->check($signedUrl); // Returns bool
      
    • Request Validation (for incoming HTTP requests):
      $isValid = $uriSigner->checkRequest($request);
      
    • Exception-Based Validation (for stricter control):
      try {
          $uriSigner->check($signedUrl, true); // Throws exceptions on failure
      } catch (ExpiredLinkException $e) {
          abort(403, 'Link expired');
      }
      
  3. Integration with Laravel Middleware: Protect routes requiring signed URLs:

    namespace App\Http\Middleware;
    
    use Closure;
    use Code4Nix\UriSigner\UriSigner;
    
    class VerifySignedUrl
    {
        public function __construct(private UriSigner $uriSigner) {}
    
        public function handle($request, Closure $next)
        {
            if (!$this->uriSigner->checkRequest($request)) {
                abort(403);
            }
            return $next($request);
        }
    }
    

    Register in app/Http/Kernel.php:

    protected $routeMiddleware = [
        'signed.url' => \App\Http\Middleware\VerifySignedUrl::class,
    ];
    

    Use in routes:

    Route::get('/protected', function () { ... })->middleware('signed.url');
    
  4. Dynamic Expiration Logic:

    • Use conditional expiration (e.g., shorter for sensitive data):
      $expiry = $user->isPremium ? 86400 : 3600; // 1 day vs. 1 hour
      $signedUrl = $uriSigner->sign($url, $expiry);
      

Gotchas and Tips

Pitfalls

  1. URI Encoding Issues:

    • Ensure URLs are properly encoded before signing. Use Laravel’s url() or Str::of() helper:
      $url = url('path?query=value'); // Automatically encodes
      
    • Fix: Decode URLs manually if needed:
      $decodedUrl = urldecode($signedUrl);
      $isValid = $uriSigner->check($decodedUrl);
      
  2. Time Synchronization:

    • The package uses the server’s time. If servers are unsynchronized (e.g., across regions), expiration checks may fail.
    • Solution: Use a centralized time source (e.g., NTP) or implement a custom UriSigner class extending the base to override time logic.
  3. Exception Handling:

    • The check() method with true throws exceptions, but these are not documented in the README. Catch:
      • MalformedUriException: Invalid URL format.
      • InvalidSignatureException: Tampered or malformed signature.
      • ExpiredLinkException: URL expired.
  4. Secret Key Management:

    • The package uses Symfony’s default secret (from SYMFONY__SECRET). Override it in Laravel’s .env:
      SYMFONY__SECRET=your_custom_secret_here
      
    • Security Tip: Rotate secrets periodically and invalidate old signed URLs.
  5. Query String Order Sensitivity:

    • Symfony’s UriSigner sorts query parameters alphabetically before signing. Ensure consistency when reconstructing URLs:
      // Bad: Order may differ
      $url = 'http://example.com?b=2&a=1';
      
      // Good: Use Laravel's URL helpers
      $url = url()->full() . '?a=1&b=2';
      

Debugging Tips

  1. Log Signed URLs:

    • Verify signatures by logging the signed output:
      \Log::debug('Signed URL:', ['url' => $signedUrl]);
      
    • Compare with manually generated signatures (e.g., using Symfony’s UriSigner directly).
  2. Test Expiration:

    • Mock time for testing:
      $uriSigner = $this->app->makeWith(UriSigner::class, [
          'time' => fn() => strtotime('+2 hours'), // Simulate future time
      ]);
      
  3. Check for Hidden Characters:

    • Use trim() or Str::of($url)->trim() to remove accidental whitespace/newlines in URLs.

Extension Points

  1. Custom Expiration Logic:

    • Extend the UriSigner class to add dynamic rules:
      namespace App\Services;
      
      use Code4Nix\UriSigner\UriSigner as BaseUriSigner;
      
      class CustomUriSigner extends BaseUriSigner
      {
          public function signWithRole($url, string $role, int $expiry = null)
          {
              $expiry = $expiry ?? $this->getRoleExpiry($role);
              return parent::sign($url, $expiry);
          }
      
          private function getRoleExpiry(string $role): int
          {
              return match ($role) {
                  'admin' => 2592000, // 30 days
                  default => 3600,     // 1 hour
              };
          }
      }
      
    • Bind the custom class in AppServiceProvider:
      $this->app->bind(UriSigner::class, CustomUriSigner::class);
      
  2. Add Metadata to Signatures:

    • Extend the signature payload to include user IDs or roles:
      $uriSigner->sign($url, 3600, ['user_id' => auth()->id()]);
      
    • Note: Requires modifying the package’s source (not officially supported). Fork the package if needed.
  3. Rate Limiting:

    • Combine with Laravel’s throttle middleware to limit signed URL usage:
      Route::get('/download', function () { ... })
           ->middleware(['signed.url', 'throttle:5,1']);
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver