No Compromises

Roles and permissions are a core part of most applications. Laravel provides some tools for managing and enforcing this, and third party packages provide even more features. Aaron and Joel share their techniques for enforcing roles and permissions, in a way that won't get harder to manage over time.

Download our free eBook of Laravel tips: A Little Bit of Laravel
Our favorite permissions package: laravel-permission

Creators & Guests

Host
Aaron Saray
Host
Joel Clermont

What is No Compromises?

Two seasoned salty programming veterans talk best practices based on years of working with Laravel SaaS teams.

Joel Clermont (00:01):
Welcome to No Compromises, a peek into the mind of two old web devs who have seen some things. This is Joel.

Aaron Saray (00:08):
And this is Aaron.
Joel, I give you permission to introduce our next topic.

Joel Clermont (00:20):
Very funny, Aaron. Because our topic today is roles and permissions but it also is a nice peek into our dynamic where I just do everything you tell me to do, so life is good. One of the core things that... I'm trying to think if there's any app we've ever built that doesn't need some sort of user permissions and I can't think of one, other than maybe a hobby project here or there. But needless to say, it's something that is frequently needed in an application. If you're going to have users, you need to have some way of defining what those users can do. Maybe today we could kick around the tools we use, the strategies we use for that and share some tips.

Aaron Saray (01:08):
Yeah. I think from a high level, when you say these permissions, what we're really talking about is authorization, right?

Joel Clermont (01:14):
Mm-hmm (affirmative).

Aaron Saray (01:14):
We have authentication, which is who is doing this thing or do we not know? Then we have authorization as then that entity or that state of being, can they have this ability to do something? Whatever that is. Then sometimes we have a context, which is to what? Can they do this to what? Can they edit this post or can they just see posts, or whatever. When we say permissions we're really talking about authorization. Then inside of there, we have Laravel gates and Laravel policies, things like that. But the thing we really kind of want to focus today on roles and permission setups, specifically how to really make use of those and then what you should be checking for and what are those best practices.

Joel Clermont (02:01):
If I go to the Laravel docs and I search for roles and permissions, I don't think I'm going to find anything. So are we going to talk about a specific package?

Aaron Saray (02:14):
Yeah, this kind of applies to any sort of roles and permission system you'd set up. But the trusted one that we reach for is the, I think it's actually called Laravel permissions. It's a package by Spatie or I'm not entirely certain. As a person who has a last name that gets mispronounced very often, I just want to say I'm sorry already for whatever I've done to that name. But you've probably heard of the company, they do a lot of work in the Laravel world.

Joel Clermont (02:43):
Absolutely.

Aaron Saray (02:44):
That is the package I normally reach for and then start to configure.

Joel Clermont (02:49):
Okay. Yeah, but like you said even though that's what we use, whether you're rolling your own system or using a different package, the general principles will still apply.

Aaron Saray (02:59):
I think when we look at those there's two building blocks we kind of talk about it, it's roles and permissions. Roles are a delicious food that I like to have with my turkey.

Joel Clermont (03:11):
Do you butter them?

Aaron Saray (03:12):
But also, roles are a type of thing that a person can be. You can be an admin, you can be an editor, you can be a salesperson, a support staff, all those different things. So it's just really a description. Then when we look at our users, which we can apply just to anything. You could apply it to a company or fish, whatever you want. We tend to only focus on users. You apply these roles, you can have... I guess a user could have no roles. Really can't do anything then, but they can have one to many roles. A user might just be an admin, or they might be support staff and they might do some sales for you, so maybe the sales staff. And maybe they are a tester, so they might have a test role or something... You can have all these different roles attached to a person.

Joel Clermont (04:06):
I'm following you so far. Maybe I'll jump in and contribute a little something here. The other big aspect of this is permissions, which is what specifically can or cannot be done. If we're going to use the mental model of a blog and a blog has posts and a post has authors. A permission would be, can I create a post or can I delete a post? Things like that, very specific things. They don't necessarily have to be tied to a database resource either, so a permission might be, "Can I see this entire feature in the application?" or something along those lines. They can be really high-level or they can be very model/policy specific. Things like that.

Aaron Saray (04:53):
I noticed you didn't make a food pun with yours, so...

Joel Clermont (04:57):
Persimmons, I think role is an easier pun to make than permissions. But point taken.

Aaron Saray (05:07):
All right. In general, you apply permissions to roles. You can say that this role, maybe a blog author role, has the permission to create posts and to edit posts and to delete posts. I should take a quick aside, you're not just saying because they have edit, post permission, they can edit every post. You'd probably mix this technology with policy so you'd want to check, do they have permission to even edit posts? Then, do they have a form of ownership of this post that they can do it to this thing?

Joel Clermont (05:46):
Correct. But anyway, can I put in aside on your aside?

Aaron Saray (05:49):
Yeah.

Joel Clermont (05:49):
One of the things I like about the Laravel permissions package is it actually builds on top of gates, so you're not doing a whole separate thing. You can easily mix and match these things in gates and policies where you might normally use them in Laravel without a package like that. But, yes, your point is very valid that there's more to it than just, "Can you do this thing or not?"

Aaron Saray (06:12):
Yeah. And that's because gates are more of a simple thing and policies are a little bit more complex in roles and permissions. Even though they can have a complex hierarchy and a collection of them, they're actually just pretty simple.

Joel Clermont (06:25):
I know what your answer's going to be, but why wouldn't you assign a permission directly to a user. Why do you do it to a role?

Aaron Saray (06:34):
Well, you can assign it to a user, the functionality exists. Like in this package, there's definitely been a few times when maybe that's something you could do for a very specific one-off. But normally, you'd have to basically decided that all the other solutions are not the right way to do it first. But it's because you want to apply these permissions to roles so that way you can reuse the permissions on other roles, and you can change and interact. For example, let's just say maybe you have a sales role and in that sales role has the ability to view sales summary data and view sales detail data, those are two permissions on that role. And later on you decide, "I want to maybe have another role," or, "Not all the users I want to see the detail because they don't need to, they should just be selling." If you had to sign it to individual users, you'd have to find all the users that now have those, make up decisions on whether they should have them or not and alter them and whatnot. Whereas with roles, you just say, "All right, that role should have it or not. If I want to assign it to other people, I'll make two roles, sales role and sales manager role, and those will have different collections of permission. So overlap or share some of the same ones.

Joel Clermont (07:56):
Yeah. I mean, really, it's a maintenance issue. If you start doing direct assignments of permissions to users, it very quickly gets out of hand. Whereas roles are kind of a nice grouping and easier to think about as you maintain the app long-term.

Aaron Saray (08:10):
Well, another aside I'd say on that one, because we're doing these asides in this episode is, as a programmer you have to remember that your business users are probably going to communicate to you as permissions. They're going to say, "I want Joel to have this permission." Just because they say that and that's the business language they understand, doesn't mean that that's the way you program it. You're responsible for programming a thing that gives them the end result but you're also responsible for having a quality code base and doing stuff. On the flip side, you could tell them once you've made a role for that that a user has that role, but don't have that argument with them. Just say, "Yep, he has a permission." Or, "She has permission not to do that as you've requested." They don't need to get into details.

Joel Clermont (08:58):
Agreed a hundred percent, yeah. We've talked mostly concepts and how to assign roles and permissions, but the flip side of this is how do we check them? Any tips and tricks on strategies for doing that effectively?

Aaron Saray (09:14):
Yeah. I think I'm going to kind of go way back before this topic and touch on authentication real quick. It can be really easy when you're first starting something to say, "Well, all users can do this thing so I'll just check for an authenticated user." And if the user is authenticated then they can do this thing. There's a lot of caveats and that's like a whole different discussion on why that's a bad idea, but really we're going to do authorization. Then authorization really is checking the permission to do something and so we want to check our permission level details on somethings. We want to check to see if this user authenticated or not, or whatever, has this permission. The reason I brought up authentications, checking for a user or not, is because it's also easy to fall into the trap of, "Maybe I'll just check for the role." Like, if you're a role of salesperson you obviously have all access to this. I'd say that's not true and that's going to cause you some issues. Again, if you're programming on that role, that bucket of stuff because what if roles change? Or, what if you know permissions for a role change? You're saying like, "Salespeople used to be able to make support entries in our FAQ, so we gave them permission on that role. If you're a role of support or a role of sales, you can edit FAQs," right?

Joel Clermont (10:42):
Yeah.

Aaron Saray (10:42):
Well, maybe now we only want certain sales people, the sales manager. Now we have to go back and edit that code every single place to find that sales role and change it to sales manager role. Whereas if we had checked permission for, can create FAQ in our one place where we define our permissions are managed, we would just make a different role and assign that to the proper people and just kind of move stuff around there. One place and it works perfectly.

Joel Clermont (11:10):
I've definitely learned that one the hard way. It's tempting-

Aaron Saray (11:13):
Me too.

Joel Clermont (11:13):
... to think in roles, especially when that's how you're creating the permissions. But, like you said, checking the permissions is much much easier to maintain than checking roles all over the place.

Aaron Saray (11:26):
When we're checking for permissions, I want to make it also clear that we're checking for a permission. We're checking for permission to do a thing, we're not checking that someone can't do a thing. Usually in these packages, they have like allows or denies or things like that.

Joel Clermont (11:43):
Right, yeah.

Aaron Saray (11:44):
But I would say it's one of those things where we want to develop an allow list. By default, everyone has no permission or they can't do anything, and you only then allow people to do stuff. So check for permission. Versus saying, I allow everyone in here and I just won't show the button I've set them up with a permission that says, "Do not edit things." You want to have an allow sort of list, I guess is what I'm trying to say there.

Joel Clermont (12:13):
Yeah. I mean that's a policy that... another thing that we've learned the hard way. Sometimes it feels like checking for a denial makes more sense, it's more explicit. But you get into some weird circumstances trying to juggle that logic and that's where security mistakes can happen too. If you don't properly layer in your mind the allows versus denies. Whereas if you just have one structured way of doing it, you don't have to do as much mental gymnastics to keep track of it. Something else that we've found useful for roles and permissions is something that's also called feature flags. Which is basically, let's say you're developing a new feature and experimental or it's not something you're quite ready to release to the world, but you want to get it out to a subset of your users and maybe even in the production environment. A feature flag would allow you to toggle it on or off. If you couple that idea with roles and permissions, it lets you toggle a feature on for just a specific set of users while you're in that testing mode.

Aaron Saray (13:17):
Yeah, and that's where, like we talked about, you could have a role for that or in very segmented situations you could then add that permission directly to a user or two. That there's nothing special about them except for you just happen to know them and they said that they would test this thing out for you and you have a good relationship with them or something. I would add that if you're developing a roles and permission system and then you need feature flags, this is a way to do that. It's really nice if you make your mind think of that direction. But there are other services and things out there that are for more complex feature flags.

Joel Clermont (13:53):
For sure.

Aaron Saray (13:53):
But we're talking about just the very first level here. There's no A and B testing with this, there's no reports when you're done or anything like that. But sometimes you have to push something out and maybe you just kind of put a permission there. Instead of a bunch of if statements all over, do you have to remove? It could be as simple as just making one change and giving that permission then to every single user. Then later on, you can start to remove those permission checks because they're no longer necessary.

Joel Clermont (14:23):
Yeah, really useful approach.

Aaron Saray (14:30):
Joel, why do you think that aliens don't contact us if they exist?

Joel Clermont (14:37):
Wait a second, what? They haven't?

Aaron Saray (14:40):
Well, okay. But if there is aliens, are there any reasons you could think why maybe they would just hold off on showing up and saying hi?

Joel Clermont (14:53):
They have access to our social media and would that be part of their determination?

Aaron Saray (14:59):
It could be.

Joel Clermont (14:59):
Okay, that could be a reason. These guys seem a little iffy.

Aaron Saray (15:04):
Well, they're probably seeing people that are tweeting stuff like, "Bull," in a China shop. It's like, "No, it's Bull. B-U-L-L." Or like, "All intents of purposes." Like, "No, it's all intense and purposes." Or, escape goat, that was the one I heard the other day. I'm like, "No, it's not an escape goat. It's a scapegoat." I think if they have access to Twitter, they're probably like, "Nope, they're too devolved yet."

Joel Clermont (15:36):
Twitter or maybe 9th grade English essays, things like that.

Aaron Saray (15:42):
Or Netflix, right? We get super proud, especially in America about Independence Day. Yet if you watch that movie, all we do is kill aliens.

Joel Clermont (15:52):
Yeah.

Aaron Saray (15:52):
I mean, there's tons of movies where all we do is kill aliens. Even some of our video games, it's like, "Yeah, there's some aliens. Let's just destroy them." Then I think probably the more realistic thing would be... I mean realistic in this topic, is that maybe, like you said, maybe they have but every time they try to contact us anyone who brings it up we label as sort of crazy. They're like, "Well, we have giant spaceships so we have to land in Nevada and Utah where there's no people, because we're really trying not to destroy your towns like in all your movies."

Joel Clermont (16:31):
It's a courtesy really.

Aaron Saray (16:32):
Yeah. And it's like, "Well, why did one guy out in a trailer in Nevada is the one that they chose to talk to?" Well, they're probably surprised too, like, "Where is everybody? I guess we'll talk to Billy Bob."
If you need help developing a permission system that's both secure but flexible, we can help.

Joel Clermont (16:50):
Head over to our website at nocompromises.io and book a free consultation call.