Security Tip: Test for Missing Authorisation
[Tip#48] We write tests for everything else, so why not write tests for authorisation as well?
#1 → Exposed API Keys & Passwords
#2 → Missing Authorisation
#3 → Missing Content Security Policy (CSP)
#4 → Missing Security Headers
#5 → Insecure Function Use
#6 → Outdated & Vulnerable Dependencies
#7 → Cross-Site Scripting (XSS)
#8 → Insufficient Rate Limiting
#9 → Missing Subresource Integrity (SRI)
#10 → Insufficient Input Validation & Mass-Assignment Vulnerabilities
In my experience auditing Laravel apps, the most common cause for missing authorisation is due to the developer forgetting to include an authorize()
call within a controller action. It’s far less common to forget when authorisation is handled within the routes file, but it can be easily missed in there too, so I’m talking to everyone here!
Forgetting authorisation is super easy to do - you’re adding your route, writing your controller action, thinking about the logic, where the inputs go, the validation rules you need, which jobs and events are dispatched, and what is returned to the browser. But somewhere in there you’ve forgotten to check if the user has permissions to actually do any of it…
So how do we avoid this trap? Write tests that specifically check for permissions, alongside your feature and unit tests!
If you think about it, it makes perfect sense. We write tests that cover the success and failure states of our features - ensuring everything works as expected, and nothing is broken accidently in the future. So we really should be writing tests that check we’ve implemented authorisation correctly, and that it doesn’t break in the future.
When I’m writing tests, I try to hit each of these use cases:
- Guest request
- Not allowed user request
- Allowed user request
I typically use one of these assertions in my tests (here is the full list):
$this->assertStatus($status);
$this->assertUnauthorized(); // 401
$this->assertForbidden(); // 403
$this->assertNotFound(); // 404
$this->assertRedirect($url);
Once you get in the habit of writing these tests, you’ll start automatically writing them when adding new routes, making it harder to forget authorisation. You’ll also find you consider authorisation and permissions more, potentially avoiding assigning the wrong permissions or leaving access too open on sensitive routes.
Authorisation Resources
To learn more about Authorisation in Laravel, you can find all of the past Tips at: https://securinglaravel.com/t/authorization.
Also check out these articles:
If you've made it this far, please share this Security Tip and Securing Laravel with your Laravel friends, colleagues, and enemies! The more folks we have learning about security, the more secure code will be written, and the safer the whole community and our users will be. Also, if you tag me I'll give it a retweet, and you can find all my socials on Pinkary.