Sometimes the data that flows from the backend of your application to the frontend can reveal more than you want to.
Image an ecommerce scenario where every time an order is completed, a record is added to the orders table. Now imagine that you want your customers to be able to view their own orders within their own frontend account area. If you use standard incrementing IDs to identify these orders, you could easily reveal to that user the amount of orders your site gets in a time period.
What are your options?
The first option is to use UUIDs as your primary key on a table. This is probably the most robust method but it comes with a few downsides:
- You can’t order records by insert order
- Your database size is bigger
- UUIDs can be pretty long
The second option is to use a standard incrementing primary key internally, but obfuscate it whenever its sent to the frontend.
Challenges of obfuscation
Of course, models pass from backend to frontend and vice-versa in a myriad different ways and having to manually apply obfuscation and de-obfuscation every time would be immensely tedious and limit your use of the Laravel framework in some ways (e.g. route model binding).
Additionally, you need a robust way to encode and decode your IDs to ensure that they always resolve to the same underlying key. You also don’t want this process to be easily implementable by an unconnected party (thus making standard encoding with base64, MD5 et al. off-limits).
The solution
This Laravel package tackles most of those challenges. Once the trait Obfuscatable
is applied to your model, the following actions are automatically taken:
- Obfuscated keys are resolved when used in route-model-binding.
- Model
find
functions work with either the original key, or the obfuscated one - An attribute of
obfuscatedId
is automatically appended to your model instance to allow you to reference it internally - The ID is obfuscated when the model is sent to the frontend via the model’s
toArray
function - Encoding and decoding is seeded using a custom key in your config
- You can pad the ID character length to whatever you like
- You can even define your own alphabet to use for the obfuscated IDs
- Applies a filter to IDs to prevent them accidentally creating offensive strings
Usage
After installing the package, simply add the supplied trait to any models you want to have the ID obfuscated on:
1use EvoMark\LaravelIdObfuscator\Traits\Obfuscatable;2
3class User extends Authenticatable4{5 use Obfuscatable;6}
Obfuscatable
models will also feature automatic decoding when using the model’s find
-style functions: e.g. find
, findOrFail
, findMany
, findOrNew
, findOr
// SomeController
/** * @param string $id The obfuscated order ID */public function index($id){ $order = Order::find($id);}
Validation
Laravel ID Obfuscator comes with a built-in rule extension for validating incoming obfuscated ids, simply:
public function store($request){ $validated = $request->validate([ 'id' => ['required','id_exists:users'] ]);}
Facade
You can access the encoding and decoding features anytime via the provided facade.
use EvoMark\LaravelIdObfuscator\Facades\Obfuscate;
$encoded = Obfuscate::encode(5);$decoded = Obfuscate::decode($encoded);
Config
You can publish the package config by running the following Artisan command:
php artisan v:p --provider="EvoMark\LaravelIdObfuscator\Provider"
Setting | Type | Default | Description |
---|---|---|---|
seed | string | laravel-id-obfuscator | A seed string for the encoder |
length | int | 8 | The amount of chars to pad the output to |
alphabet | string | [a-zA-Z0-9] (as string) | The alphabet to use when encoding IDs |
Limitations
- Laravel ID Obfuscator can only be used on incrementing primary keys