Security Tip: Watch out for Resource Authorisation
[Tip#50] Watch out when you mix Resource Controllers and Authorisation with custom Controller Actions and custom routes... you may find you're lacking authorisation without realising it!

During a recent security audit, I discovered heavy use of Resource Controllers and Resource Controller Authorisation. It’s a common pattern and one I’m very familiar with, but there was a twist this time…
Take a look at their routes (or at least a variant that protects the guilty):
Route::get('/books/all', [BookController::class, 'all']);
Route::get('/books/export', [BookController::class, 'export']);
Route::resource('book', BookController::class);
And the controller looked like this:
class BookController extends Controller
{
public function __construct()
{
$this->authorizeResource(Book::class, 'book');
}
public function all(Request $request)
{
return ...;
}
// Typical resource actions
public function export(Request $request)
{
return ...;
}
}
Now I can see exactly what they were thinking here: authorizeResource()
handles authorisation for controller actions, so they don’t need any manual authorize()
calls. But guess what happens when a non-standard action is used?
Authorisation is skipped entirely, allowing any authenticated user full access to these extra endpoints! 😱
In my example it’s called Books, but what if it was Users, or Patients, or Contracts? You can quickly see the problem here, as any authenticated user can access any of these unprotected routes.
My Recommendation: Avoid mixing authorisation systems and either use resource controller authorisation without custom actions, or authorise on every action. It’s more tedious, but makes you less likely to forget authorisation. Or, as I’ve said before, if you put authorisation on your routes via middleware, it's harder to forget and easier to review.
During my audit I was able to create a free trial user, and discover (via Ziggy) unprotected routes that provided me with their entire client database, all via an unprotected export route in their admin tools! Super easy to find and exploit, and they completely missed it.
This is the reason I do my Security Audits - issues like these can be so easily overlooked by dev teams, who are so used to seeing their own code and making assumptions without realising it. Often it takes an independent 3rd party with fresh eyes to look at your code before vulnerabilities are discovered, and it’s far better for that 3rd party to be a friendly hacker working for you than a malicious hacker working against you.
If you found this security tip useful, subscribe to get weekly Security Tips straight to your inbox. Upgrade to a premium subscription for exclusive monthly In Depth articles, or drop a coin in the tip jar to show your support.
When was the last time you had a penetration test? Book a Laravel Security Audit and Penetration Test, or a budget-friendly Security Review!
You can also connect with me on Bluesky, or other socials, and check out Practical Laravel Security, my interactive course designed to boost your Laravel security skills.