Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
August 22, 2021 06:36 pm GMT

Do not expose database ids in your URLs

When developing web apps, we often rely on fetching informations from the database. Frameworks offer a way to make this easy thanks to ORMs.

Most of the time, the ORM will find your model using the primary key as a reliable identifier. On the vast majority, primary keys are auto incremented integers.

Your URLs then look like this:

https://example.com/cart/12https://example.com/user/15/post/41...

Providing an incorrect or faulty authorization layer can create data leaks: users become able to navigate from data to data, which is something we would not want to allow if it is about sensitive data like users personal info.

Obfuscating the identifier

An easy way to mitigate this security breach is to use a key that is:

  • Hard to predict
  • Random enough to be able to create a lot of items while keeping the unicity between them
  • Easy to generate from your code and the database
  • Checkable (we can know by analyzing its integrity if it is valid or not)

Thanks for us, UUIDs are a very good candidate for it. It checks all the points above, and are very easy to use thanks to a wide range of package ready for use.

Your URLS now become harder to predict, which mitigate any developers mistake regarding authorization policies in your app:

https://example.com/cart/f6e4208f-5df4-466e-9225-01f296e2a09chttps://example.com/user/b1b44b12-34bc-4ed7-a666-9657b8b8c31b/post/e530d034-42f7-467b-91e3-1cc9313312eb

Example on a Laravel app

In order to practice developing a Laravel package, and using my first ever Github Workflow, I created a package to make this job a breeze.

Here is how you can use khalyomede/laravel-eloquent-uuid-slug in your app now.

Install the package

First, head in your console, and type this command:

composer require khalyomede/laravel-eloquent-uuid-slug

Add your slug column to your migration

Then, go to the migration of the model of your choice, or create a new one if it has already been installed, and add the slug column.

namespace Database\Migrations;use App\Models\Cart;use Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema;final class AddSlugColumnToCartTable extends Migration {  public function up(): void  {    Schema::table('carts', function (Blueprint $table): void {      Cart::addSlugColumn($table);    });  }  public function down(): void  {    Schema::table('carts', function (Blueprint $table): void {      Cart::dropSlugColumn($table); // available soon in v0.2.0    });  }};

Add the trait to your model

This is the last step, which will help configure how your model is retreived in your routes using Route model binding.

namespace App\Models;use Illuminate\Database\Eloquent\Model;use Khalyomede\EloquentUuidSlug\Sluggable;final class Cart extends Model{  use Sluggable;}

Use it in your controller

Now you are ready to take advantage of the package. The great thing with it is that your code does not change! You can keep using the route() method like you are used to.

// routes/web.phpuse App\Models\Cart;use Illuminate\Http\RedirectResponseuse Illuminate\Http\Request;use Illuminate\Support\Facades\Route;use Illuminate\View\View;Route::get("cart/{cart}", function (Cart $cart): View {  return view("cart.show", [    "cart" => $cart,    "saveCartRoute" => route("cart.store", $cart),  ])->name("cart.show");});Route::post("cart/{cart}", function (Request $request, Cart $cart): RedirectResponse {  $cart->update($request->only(["name"]));  return redirect()->route("cart.show", $cart);})->name("cart.store");

And voil! This package will no interfer with your existing logic as you can see. The only thing that changes is now your routes are not exposed.

route("cart.show", $cart); // https://example.com/cart/398e76a7-7c16-467c-93a8-04c06c6df703

Conclusion

While this solution is not a magic way to resolve the initial problem of data leak, I find it is a very easy actionable mecanism to reduce the possibilities for malicious users to trick your system.

This does not prevent you to add an authorization or guard mecanism, like Laravel Policies for example. For example, if a user navigates to a cart that have not been created by him/her, should not be able to view it.

Other folks here already talked about this subject, so make sure to give it a go if you want to read more about using UUIDs:

Happy URL hardening!


Original Link: https://dev.to/khalyomede/do-not-expose-database-ids-in-your-urls-567

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To