laravel-encrypted-route-params maintained by imran
Laravel Encrypted Route Params
🔒 Stop ID Scraping & Leakage with Transparent URL Encryption
Are you still exposing raw database IDs in your URLs?
https://your-app.com/invoices/1024
The Problem
Exposing raw IDs is a major security and business intelligence risk:
- ID Scraping: Competitors can easily guess next/previous IDs to scrape your data.
- Business Intelligence Leakage: Anyone can see exactly how many orders, users, or invoices you have just by looking at the URL.
- Insecure Direct Object Reference (IDOR): While middleware should prevent unauthorized access, raw IDs make it tempting for attackers to probe for weaknesses.
- Ugly URLs: Raw IDs feel "naked" and less professional than modern, obfuscated identifiers.
The Solution
Laravel Encrypted Route Params provides a seamless, "drop-in" way to encrypt sensitive path parameters using Laravel’s native Crypt facade.
It handles everything automatically:
-
Transparent Encryption: Use
route()as normal; it encrypts the parameters on the fly. -
Automatic Decryption: Middleware decrypts values before implicit route model binding, so your controllers don't even know it happened.
-
Shorter Tokens: Optional compact mode for cleaner, shorter URLs.
-
JSON Support: Can also decrypt tokens inside JSON request payloads.
-
PHP
^8.1 -
Laravel
^10.0|^11.0|^12.0|^13.0 -
A valid
APP_KEY
🚀 Installation
composer require imran/laravel-encrypted-route-params
The package is auto-discovered. If discovery is disabled, register the provider manually:
// config/app.php
'providers' => [
// ...
Imran\EncryptedRouteParams\EncryptedRouteParamsServiceProvider::class,
],
⚙️ Quick Start
1. Middleware Setup (Required)
Decryption must run before SubstituteBindings.
Laravel 11 / 12 / 13 (bootstrap/app.php)
use Illuminate\Foundation\Configuration\Middleware;
use Imran\EncryptedRouteParams\Middleware\DecryptEncryptedRouteParameters;
return Application::configure(basePath: dirname(__DIR__))
->withMiddleware(function (Middleware $middleware) {
$middleware->web(
remove: [\Illuminate\Routing\Middleware\SubstituteBindings::class],
append: [
DecryptEncryptedRouteParameters::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
);
})
2. Usage on Routes
Just add ->encrypted() to any route definition:
use Illuminate\Support\Facades\Route;
// Encrypt the {invoice} parameter automatically
Route::get('/invoices/{invoice}', [InvoiceController::class, 'show'])
->name('invoices.show')
->encrypted();
3. Generate URLs
Just use the standard route() helper! If transparent_url_generation is enabled (default), it just works:
// Generates: https://app.com/invoices/eyJpdiI6Il... (encrypted)
$url = route('invoices.show', ['invoice' => $invoice->id]);
🏛️ Model-Level Control (Automatic)
Instead of marking every route, you can enable encryption directly on your Eloquent models. This is useful for sensitive IDs that should always be encrypted in URLs and JSON responses.
1. Add the Trait
Add HasEncryptedAttributes to your model and define which attributes should be encrypted:
use Illuminate\Database\Eloquent\Model;
use Imran\EncryptedRouteParams\Traits\HasEncryptedAttributes;
class Invoice extends Model
{
use HasEncryptedAttributes;
/**
* The attributes that should be encrypted in URLs and toArray().
*/
protected $encrypted = [
'id',
'customer_id',
];
}
2. What this does:
- Automatic URLs:
route('invoices.show', $invoice)will now automatically produce an encrypted URL, even if the route is NOT marked with->encrypted(). - Automatic JSON: When you return the model from a controller or call
$invoice->toArray(), the listed attributes will be encrypted automatically. - Transparent Decryption: The middleware automatically detects models using this trait and decrypts the route parameters before they reach your controller.
🛠️ Advanced Features
Selecting Specific Parameters
// Only encrypt 'invoice', leave 'org' as plaintext
Route::get('/orgs/{org}/invoices/{invoice}', ...)
->encrypted(only: ['invoice']);
// Encrypt everything except the 'slug'
Route::get('/u/{user}/{slug}', ...)
->encrypted(except: ['slug']);
Shorter Tokens (cipher = compact)
Tired of long Base64 strings? Switch to compact mode in your .env:
ENCRYPTED_ROUTE_PARAMS_CIPHER=compact
This uses AES-256-GCM + HKDF to produce significantly shorter tokens while maintaining high security.
JSON API Support
Decrypt parameters sent inside JSON POST bodies automatically by adding the middleware:
Route::post('/api/invoices', ...)
->middleware([\Imran\EncryptedRouteParams\Middleware\DecryptEncryptedJsonRequestParameters::class]);
Configure which keys to decrypt in config/encrypted-route-params.php.
📄 Configuration
Publish the config file:
php artisan vendor:publish --tag=encrypted-route-params-config
Key options include failure (404 vs 400), log_failures, and max_plaintext_length.
❤️ Support the Project
This package is free and open-source. If you find it useful, please consider:
- Starring the repo on GitHub.
- Reporting bugs or suggesting features via Issues.
- Contributing code via Pull Requests.
💖 Sponsors
If your company uses this package in production, please consider sponsoring development to ensure its long-term maintenance. Contact silent.lips125@gmail.com for sponsorship opportunities.
🤝 Contributing
Please see CONTRIBUTING for details.
🔒 Security
If you discover any security-related issues, please email silent.lips125@gmail.com instead of using the issue tracker.
📜 License
The MIT License (MIT). Please see License File for more information.