In Depth: Policy Objects
[InDepth#8] Policy Objects are incredibly powerful. Use them.
Greetings, my friends! After last month’s In Depth being delayed by due to COVID1, it’s great to be back on schedule. I hope you found the reminder about what randomness functions to use last week helpful - and enjoyed the list of not-random methods I’ve encountered in the wild!
This month we’re going to dive into Policy Objects, looking at how they work and the various tricks you can do with them to make authorisation easier. Long term readers may remember we covered Policy Object filters back in Tip #2, but I felt it was time to cover everything.
👉 I offer Laravel Security Audits, so please reach out if want me to hack you site and audit the security of your Laravel app. I’m currently fully booked until August/September, so if you want an audit this year, you’ll need to book in soon.
Policy Objects are a seriously underrated component in Laravel. They are so underrated that they don’t even get their own menu item in the documentation - you need look under “Security → Authorization” to even find them! Even typing “policy” or “policy objects” into the search doesn’t pop on them either… it’s upsetting…
Ok, maybe it’s not that bad, but they really are seriously underrated. So I’m hoping to undo the damage by teaching you about Policy Objects.
Strap in, we’ve got a lot to cover!
What Are Policy Objects and Why Use Them?
A Policy Object is a class that organises authorisation around a specific model or resource. They allow you to store your authorisation logic in a single place, making it easy to review and change your authorisation rules without needing to find any instances throughout your application. Laravel will automatically inject the authenticated user for comparison, supports auto-discovery and filters, allows additional context, and lets you check authorisation on models, in controllers, as middleware, and even inside blade!2
You should create a Policy for each model or resource that you need to authorise user activity around, and a method for every ability you wish to authorise. Even if the authorisation logic is trivial and/or you only need a single ability for that model, it is still beneficial to create a Policy for each model. They let you separate your business logic from your authorisation, keeping your code cleaner and giving you a logical and easy to find place where all of your authorisation rules exist, making it easy to review and update as things change over time.
Since some super smart person clearly thought that giving two confusingly similar concepts, authentication and authorisation, two confusingly similar names was a brilliant idea, let’s define them both to remove the confusion:
Authentication → You are who you say you are. I.e. When you login with your credentials, you prove you are the owner of the account3.
Authorisation → You are allowed to do what you’re trying to do. I.e. Only users with edit permissions can edit a post.
Since there are multiple ways to check policy authorisation depending on the situation, we’ll cover how to create and write policies first.
You create Policy Objects using the
make:policy artisan command4:
$ php artisan make:policy --help Description: Create a new policy class Usage: make:policy [options] [--] <name> Arguments: name The name of the class Options: -m, --model[=MODEL] The model that the policy applies to -g, --guard[=GUARD] The guard that the policy relies on
To create a new policy for a
Post model, all we need to do is this:
php artisan make:policy PostPolicy --model=Post
Laravel will create a new policy class for you:
Keep reading with a 7-day free trial
Subscribe to Laravel Security In Depth to keep reading this post and get 7 days of free access to the full post archives.