The Laravel Podcast

Authorization and Authentication, with Joseph Silber

Episode Summary

If your app has users, it's likely you're going to want to know who they are and what they can--and can't--do. Take a listen to this introduction to the two "auth"'s, authentication and authorization, and how they work in Laravel.

Episode Notes

 

Episode Sponsorship

Transcription sponsored byLarajobs

Editing sponsored byTighten

Episode Transcription

Matt Stauffer:
Welcome back to Laravel Podcast, season four. Today we're talking to Joseph Silber, one of the unsung heroes of Laravel community, a core contributor, and also unexpectedly a fantastic clarinetist. Stay tuned.

Matt Stauffer:
All right. Welcome back to the Laravel Podcast, season four, where every single episode is about a single topic. And today our topic is about authentication and authorization. So I am happy to be joined by Joseph Silber, whose name you may not have heard before, but hopefully we're going to change that soon. Now he did recently have an opportunity to speak about Lazy Collections on the Laravel meetup. And so you might be asking, "Now, wait a minute, wasn't he the collections guy a minute ago and now he's the authorization authentication guy?" Well, what he really is, is the guy that writes a whole bunch of stuff that not a lot of people, except those of us who watch the commits come through to Laravel see. And so he has been writing, committing to Laravel for years and years. And a lot of us when I'll even mention, "Hey, I'm interviewing Joseph."

Matt Stauffer:
Someone will say, "I've seen that name before, where have I seen that name before?" I'm like, "If you've ever looked at the layer of out commit logs, that's where you've seen him before." So today we're going to be talking about authorization and authentication. I'm going to give just a quick high-level intro to those, just to differentiate them. That's it. And then I'm going to ask Joseph to introduce himself and kind of we're going to walk into our normal five-year-old topics. So really quick authorization authentication. When we say auth A-U-T-H we often mean the two of these. So Joseph is going to be talking about the difference between them and all that kind of stuff. But I just want to know that when people are talking about Laravel's auth system or something else auth system, they're almost always talking about these two in tandem.

Matt Stauffer:
It's very convenient that they both happen to start with the four letters, A-U-T-H but just remember that if someone says auth, you don't know if they mean authentication or authorization or both, so it's good to be specific. And during the span of this conversation, we will try to be specific about which one we're talking about. All that set aside. Joseph, can you tell the guests a little bit about yourself? I mentioned all these contributions you're doing, but if you're just meeting somebody and you say, "Hey, here's who I am. Here's what I do." How do you introduce yourself?

Joseph Silber:
Yeah. Hi. It obviously it depends on-

Matt Stauffer:
It depends on the context of course.

Joseph Silber:
It depends on the person. Usually when people ask me, I just found whatever I say ends up being too much headaches. Usually when I say is I do computers.

Matt Stauffer:
Computers. Yup. So if somebody's-

Joseph Silber:
So can you fix my printer?

Matt Stauffer:
Yeah, exactly. So if somebody is a computer programmer, how do you answer them? If they understand what this all means?

Joseph Silber:
Usually I say I'm a full stack developer, web developer.

Matt Stauffer:
Got it. And it's funny because I was asking you before, we chatted a little bit beforehand and I said like, "Should I say, he's the leader of this." Where he's like, "Just a general." I don't know what you said, kind human or nice human. I like that. He's a good guy. He does a lot of good stuff and he has a lot to teach us. And one of the reasons he's here for this one is he has among his many contributions have been a lot of the stuff related to authorization and authentication. So let's just jump right into that. So we're going to take each of them separately. If you were to describe authentication as it exists in a full step application like Laravel, to a five-year-old, what's the simplest possible way to describe what authentication is and what it does.

Joseph Silber:
So I would say authentication is about knowing whom you're talking to. Somebody knocks at the door, you ask, "Who's there." You don't just let anyone in. You don't just open the door. "Aunt Sally is there." So either you recognize Aunt Sally because you know her name or because you recognize her voice or because you're looking through the people and you recognize her face. Those are biometric, that's a very adult word, but that's biometric authentication. Or if you have a tree house and somebody wants to come up and you ask them, "Hey, what's the passphrase." And they have to say a magic word. All of these are authentication. You're trying to authenticate to make sure that the person is who they say they are.

Matt Stauffer:
Yeah. I love that. That's fantastic. And that's good for a five-year-old too? Nice work.

Joseph Silber:
I think so.

Matt Stauffer:
So let's talk about for authorization, what's authorization for a five-year-old?

Joseph Silber:
So now once you already know whom you're talking to, you have to know what can they do. So if it's just a stranger that you don't really know, I mean, you know who they are, they live a couple blocks down. You're probably not going to let them into the house. If it's the mailman, you might let them into the house, they drop the package and they leave, but you're not going to let them into the house proper. And maybe if it's Aunt Sally, she can come in and she can come to the kitchen, but maybe not at the dad's office. So everybody gets a different set of authorization, what they are allowed to do, even after we know who they are.

Matt Stauffer:
Yeah. Also perfect for a five-year-old because children perfectly understand that there's certain things that some people can do. Well, they at least purportedly understand most things. I don't know if they actually truly understand it. I love that. I love that very much. So if we were to talk about what authentication and authorization look like in Laravel specifically, there are some built in systems for some of these things and sometimes when we reach for external systems. What is the basics of what it looks like to do authentication for starters in Laravel, where would we be seeing this? And is it something we always have, or we only have a certain context. So what does authentication in Laravel look like?

Joseph Silber:
So before we get into the actual technologies that power it. It's just, whenever you see a log in form and you're typing in your username and your password, then is authentication. That's the most basic format. Now how it works under the hood, we can talk about many, many different ways. The sessions, cookies, basic auth, JWT auth, we can go through the whole plethora of ways of how you can do that. But using a username and password to log in, that is where it all starts. Now the basic authentication in Laravel works with cookies. And the way that works is that when you log in and you give it a username and password, Laravel is going to look up that username and password in the database. If it finds that username and password, it's going to know who you are. Once it knows who you are. It stores that information in what's called the session, a session is a way of knowing when subsequent requests come into the system and you want to know each request who made that request.

Joseph Silber:
The way to connect multiple requests to one another is through the session because generally speaking HTTP is what's called stateless. So you make an HTP request and when the HTTP request comes into the server, the server does know about previous requests, the way for the server to tie several requests together is through something called a session. And the way session works is through cookies. Cookies are a tiny piece of data that when you first make a request to the server, the server sends back that tiny piece of information. It's like sort of a token and the browser stores that token. Any subsequent requests that the browser later makes to the server, it always sends along that same cookie, that same token. So Laravel being the server that receives those requests can take that cookie, that tiny token and look it up in what's called a session.

Joseph Silber:
So Laravel sessions by default are stored on the file system, but you can also store them in the database. You can store them in Redis and Memcached, there're many different drivers, but by default, you really don't have to worry about it. You just it's plug and play. This is all what happens behind the scenes. So when you log in, once Laravel identified who you are by looking up your username and password in the database and pulling out the user record. It's going to store in the session who you are, so that all subsequent requests, it's already going to know who you are. You're not going to have to reauthenticate every time.

Matt Stauffer:
Yeah, that's good. So primary mode of doing authentication is going to be that username, that password. And then it's going to be stored in a session. What are the next one or two most common ways where people authenticate into Laravel apps, not through username and passwords?

Joseph Silber:
So a big one would be probably token auth. Token auth is usually used for either mobile apps or third-party systems that have to connect to your app somehow. And they just get a token. And that token is sent every time you make a request. So instead of getting in a way, you're also sending a token with cookies, but the cookie is the token that's being sent, but you're already logged in with a token authentication, every request includes a token, usually in a header, but every request is separately authenticated. That's another one.

Matt Stauffer:
Yup. And so it's more truly stateless at that point, because each time it has to say here's who I am and prove it.

Joseph Silber:
Yes.

Matt Stauffer:
Yeah, absolutely. And so things like Passport and any other tools that are allowing us to integrate flows for generating and sharing an authenticating tokens. Those are all additionally authentication, but they're not core and they're not primary. And like you said, the primary authentication is usually in password and then you're logged in until you log out.

Joseph Silber:
Correct.

Matt Stauffer:
So let's talk about authorization, what opportunities and spaces for authorization are there that are built into Laravel?

Joseph Silber:
So authorization again, you can think of it as let's just think about blog posts. Because that's the canonical example that everybody uses. If you want to create a new blog post, you need authorization to do that. If you want to delete a blog post, you need authorization to do that. Any action you want to take in a system, either doing something or reading something, viewing something, you always need to be authorized to perform that action. Yeah. That's the idea. So the way it works in Laravel is Laravel has something called a gate and the gate you can think of the gate as a literal gate. Like I said before, dad's office, I'm sure that dad's office has a door and that door is usually closed. And if you want to go into dad's office, you need to be authorized to open that door and go in. So Laravel's gates from high level perspective, at least is just a series of actions that you either can or cannot do. And you can ask the gate whether you're allowed to do that or not.

Matt Stauffer:
Yeah. Yeah. I love the idea because it's basically, so with the gate in Laravel, you're defining those set of rules and then later you're asking the gate whether you can go through. So I'm imagining like a mom's office and dad's office both have a gate in front of them and each of them can have the rules defined differently. And so mom's office says, "Can mom enter at this office?" And dad's office says, "Can dad enter this office?" And each of those can have those rules defined differently. And at any point you can ask the gate by mom or Sally or whoever else pressing on the gate and seeing whether or not it opens and the open is the boolean right? Like yes can, or no cannot. And everything else has really kind of basically everything Laravel is if you're using Laravel core, you're either saying here's a gate rule or here's a tool to allow you to ask the gate, can this person do that thing, right?

Joseph Silber:
Yes. Yes. What a great rift on that original example, great.

Matt Stauffer:
And what a wonderfully simple way of thinking about something that can often feel overwhelming. I really appreciate that. Because often people, when they're thinking they're approaching the Laravel authorization, it can feel overwhelming and it really is a gate::something. And it's basically, you're saying, allow this, given this or deny this given that, and then later you're asking can, in so many different contexts, user arrow can, or using the at can thing in blade. There's all these different spaces that are just allowing you to ask the gate, can this happen given this context? That's it. And that's the super simple. Now because of the way it's built in Laravel, so we've got username and login, which is very, very, very, very common. Username and password logs, you in all kinds of stuff. And then the second one is the ACL system. Can you explain what ACL means? Sorry. I shouldn't drop that acronym.

Joseph Silber:
I know what it means. I'm trying to... It's access control or something.

Matt Stauffer:
Yeah. It's access control and sometimes people say layer and sometimes people say list. I don't even know which is the correct one. Yeah. But ACL in general just means what we just described. Mom's gate, dad's gate, it's that gate it's that definition of who can do it or not. And then the ability to ask the question of, can this person or can this entity do the same thing or not? So you've got with Laravel, you've got the built in auth. You've got that built in ACL, but with one thing and of course I'm definitely asking this because it's you, but one thing I think is most common in the authorization space that is not included out of the gate is roles. So I want to talk a little bit about how roles play into authorization and just, I think this is a perfect time to introduce your package Bouncer.

Matt Stauffer:
In what way, if somebody understands the basic ideas that authorization is asking the question of, can I do this or can I not do that? How do roles play a role in that general concept and knowing that roles aren't supported in Laravel by default, could you tell us a little bit about Bouncer?

Joseph Silber:
Yeah. So roles in general is the easiest way to think about roles is to group a bunch of people or users together and give the whole set a list of abilities at once. That's basically all it is. Back to our blog. If you are an editor, then you could probably edit posts or you can create new posts. If you're just a subscriber, then you can view posts, but you can't edit posts. So we don't want to have to give these abilities individually to each user. We want to be able to group a bunch of users together under one common name, which we're going to call a role and then give abilities to those roles.

Matt Stauffer:
Yep. I love it because one of the benefits of roles is not only that you're not having to duplicate the assignments of those things, but you're also now not having to duplicate the updating of those things because if a role gets a new ability later, you can apply it to the role and then it's instantly and applied to all the people under it. So-

Joseph Silber:
Yeah. It's like the epitome of DRY don't repeat yourself.

Matt Stauffer:
Yeah. It's so interesting because don't repeat yourself often gets overused by don't repeat your code, but the best thing about DRY about don't repeat yourself is don't repeat the logic, don't repeat the knowledge and that's exactly what you're doing there. You're not repeating the knowledge by the 50 people who are a blog manager. And then now you have to change 50 people's permissions. You assign those 50 people the blog manager role, and then you can change its permissions once. And in the family's house, there might be a role for parents and there might be a role for the person who actually works in this particular office day to day. And there might be a role for immediate family members and a role for distant family members or stuff like that. So there are all these things you can imagine in both those contexts where for some reason, these people all naturally inherit the same set of abilities, even if we don't know what the final set of responsibilities will be, but we know that they all kind of have the same reason for having access to something.

Joseph Silber:
Yeah. It's not only the more work it's if you do it individually, you might forget something.

Matt Stauffer:
Exactly.

Joseph Silber:
If you're going to do ability based on each kid, then you forget to restrict one kid from the cookie jar and that cookie jar is going to be empty.

Matt Stauffer:
That kid's going to be sick on the floor. Yep, exactly. I love that. So roles do not exist out of the box and I've seen a lot of role-based systems that try to reinvent everything from scratch. There's a lot of external authorization systems and authentication systems that you can use in Laravel that used to be a lot popular, more popular than they are today, which makes me very, because I don't think they're necessary. But one of the things I love about Bouncer is that it works with the native authorization system that's built in a Laravel. So could you tell us a little bit about what it's like to use Bouncer to add roles to a Laravel application?

Joseph Silber:
Yes. I guess Bouncer is not just about roles. It's also about permissions and maybe we should start first by talking about how Laravel is built an ACL works and how you use it.

Matt Stauffer:
Yeah. Go ahead.

Joseph Silber:
So Bouncer's built in ACL works by defining abilities on the gate. That's the simplest way so-

Matt Stauffer:
Laravel is built on the gate.

Joseph Silber:
We do gates... Yeah. Sorry. Yes. Laravel's built in gate works that way. So you write gate::define you pass it a name of an ability. So let's say a string just around the string. Anything that you use to identify some sort of action, for example, edit settings, then you pass it a function. And that function takes one parameter the user, and you return a Boolean from within that function. So edit settings and then you have to figure out whether the user can edit settings or not. So the most primitive way would be, let's say you're the developer and you're the sole person who's allowed to change settings.

Joseph Silber:
And you will just happen to know that your user ID is one. So within that callback, you can just do return user arrow ID==1. That's going to return true for you, false for anyone else. So you're going to be the only one that can edit settings. That is the most crude way to do it. So now once you have this definition, then you can query the gate and ask the gate who can do that. So the gate is connected to the session and to the authentication. So the gate always knows who is currently signed in. So at any point throughout your app, you can do gate::can, and you pass it that string. So for example, you're going to do gate, can and a string, edit settings. Behind the scenes the gates is going to call that function that you had registered for that key.

Joseph Silber:
And it's going to return your Boolean, whether you can or cannot do that given the action. Again, that's the most basic form of it. Now, obviously there are many different ways to do it and you can either check it directly or you could use blade directives. If you want to check within blade, if you could do something, can you do at can? And that at can, you pass it in that string edit settings and then let's say you have your navigation. You don't even want to show the settings navigation for somebody who can't edit the settings. Then you're just going to do at can, edit settings, put all the HTML on there and then end it. And that way, that whole section is only going to be rendered to whoever can edit settings. Now later on, as your app grows and you actually have more people that can edit settings, hopefully you have to find a better way to handle that.

Joseph Silber:
So instead of returning directly equals equals one, maybe the next step up the crudeness ladder would be to maybe have you add a column to each user. And the common user table that says can edit settings. Now within now, every user model is going to have a property called can edit settings. And from within that closure that you pass to the gate that checks if you can edit settings, you're just going to return user arrow can edit settings. So again, it's still pretty crude, but that's the next level up now you've made it more dynamic. You can have more people that can edit settings and you can actually change it as you can imagine a dashboard that has a UI where you can actually toggle this on and off on each user. Makes sense so far?

Matt Stauffer:
Yup.

Joseph Silber:
Yeah. So that's a gate and that's gate definitions, which are just simple keys that you can check. The next step on top of that is what Laravel calls model policies. So a policy is a way to group abilities for a given model. So we said before that you can do a gate and the gate can get a single key. And that key edit settings, the edit settings is not connected to anything. Back to our blog, let's say we have a model called blog, class blog. That's our model. We have a database, we have in database we have a table it's called blogs. And now you want to know on each individual blog, whether the user can edit that blog. Now, maybe it depends on whether the user created it. Maybe if you created a blog, you can update it. So obviously you can still do that with just close your callbacks on the gate, but that gets very hairy. And the more you-

Matt Stauffer:
Yup. You sort of have like a name spacing, right? Like edit blog, add blog, delete blog. And there's just those ungrouped strings. It feels kind of gross.

Joseph Silber:
Yeah. So in order to simplify this whole thing, Laravel has an idea called a policy. A policy is a simple class. You can generate it through Artisan. And I think it's artisan make:policy and you generate a policy. Let's say you have a user policy. And on the user policy, you can have multiple methods, each method corresponding to a different ability that you want to allow or disallow on any given model. So for example, on the policy class, you can have an update method. The update method takes a user, and then it takes an actual instance of a post of a blog post. Now you can call gate::can, and let's say, hey, you just going to pass in a string update. You're not going to say like we said before, edit settings, it's just going to be generic update.

Joseph Silber:
And then you pass it as the second argument. You're going to pass it the actual blog post. So again, it's gate:: open( and you pass a string update, well gate::( You pass it in a string update. And then you pass it on a second argument, which is going to be the actual post instance. And that is going to call the user, the post policies, update methods. It's going to pass at the current user. It's going to pass at the post, the actual post. So now imagine it, like we said let's say you only want to allow the original author of a given blog post to be able to edit it. So within that method, the update method, you're going to return user arrow ID equals equals post arrow, user ID or creator ID or whatever-

Matt Stauffer:
Author ID or whatever you call it.

Joseph Silber:
Yeah. Whatever you call it. So that is not the next level. That that is like up to where Laravel works, Laravel unless you do these dynamic things. But again, if you start doing more and more of these and you want to have many, many more abilities and you want to store them probably in the database, because you want it to be dynamic. You want to have a dashboard maybe where you allow your admins to give rights to certain people, either to certain users directly, or to groups of roles. Laravel doesn't really have built in supports for that. Laravel's abilities and policies are static. They're hard-coded within the code. There's no way to change them at runtime. So that's what a package like Bouncer is trying to achieve that you should have a weight through the UI of your application to add and remove roles or add the remove abilities from roles and from users.

Matt Stauffer:
Yeah. That's beautiful. And so I actually have only ever interacted with the roles aspect of it. Does it come up with its own pivot structure on its own already for all this stuff?

Joseph Silber:
Yes. It comes with it's own migrations. Yeah.

Matt Stauffer:
Okay. Yeah. So if you've ever find yourself in a context where just as Joseph was just describing, you are building those closures and realizing, you know what, I need to be able to define all these things. What's the best database structure? And oh, I allowed this person to be assigned a single role by adding a role underscore ID to the user and then a roles table or something like that. But then you realized you also wanted to be able to do roles, but then the client also wanted you to say, well, yeah, but that role, plus this one ability, or maybe all of a sudden they have to have multiple roles or something like that. So you can do those things in Laravel, but it's not as if Laravel doesn't support you doing it, but it's not defined how to do those things. So Laravel takes you up to one point and then you have to make that structure up.

Matt Stauffer:
And so what Bouncer does is it has an opinion of how to do that structure and a whole bunch of tooling built around it. So you don't have to reinvent that kind of second half of it every time. Is that like a good way of describing it?

Joseph Silber:
Yes. Well, crucially, like you said before, you mentioned it before in passing, but I just want to be clear about that. Many of the ACL libraries out there are completely standalone. And once you use them, they're not fully integrated within Laravel. There are a few packages and Bouncer is one of them, that's fully, fully integrates within Laravel. So when you use Bouncer, you're only interacting with Bouncer when you grant abilities or when you remove abilities or roles, et cetera. This is not a tutorial for Bouncer. But once you get everything into Bouncer, Bouncer takes care of everything. From that point forward, whenever you want to check abilities or you want to authorize routes or resources, anything you do from that point forward, you do the standard way with Laravel. Because the way bounce works is it hooks into Laravel's own gate and everything you register in the database ends up being registered at runtime within Laravel's gates. So whatever you check at the gate is actually going to be checked through Bouncer. So there's nothing left for you to do.

Matt Stauffer:
Does it do a single query when each kind of request loads that loads all the information needed for the current user to figure so that gate can answer it?

Joseph Silber:
Yeah. So it has multiple modes that you can set depending on what you need. So by default, what it does is as soon as you make a request for any sort of authorization, for a single authorization request for one, for a user, it's going to create a database for all of their abilities, hold all their abilities in memory, because most likely subsequent checks are going to be for that same user. Sometimes people have hundreds or thousands or even literally tens of thousands of abilities, then it doesn't make that much sense. So it has a mode where you can set it so that it only pulls a single ability at a time.

Matt Stauffer:
Got it. I love it. We could obviously do a whole podcast on Bouncer, but I wanted to make sure, because I think that the number of times that folks have come to me, not understanding what's possible within Laravel and also not understanding the best way to go about moving past what Laravel offers by default is it's just crazy. And it's crazy also in part, because so first I think it's because many of the large auth systems are adaptations of ideologies or actually code that existed before Laravel had full ACL. And so we're working with a client right now that has one of the larger and most out of date layer of authentication libraries built in. That was the biggest library, but now it's not hooked into Laravel core like you're saying. And so now they're forced to be kind of really separate from the Laravel way of doing things in a lot of ways.

Matt Stauffer:
And so for me, I'm always saying, I want to keep it as close to the core as possible. And most of the time when somebody is using an external package, I'm like, are you sure you really need that package? But this is a circumstance where you do, but come on, use the lightest package you can that hooks in. So anyway, that's one of the reasons why I'm super grateful for Bouncer, but, okay. So let's move on a little bit. We've talked a little bit about what authentication is and authorization and I'm sure more of it will come up. But usually the next kind of point I come to at this point is when's the last time you used the system?

Matt Stauffer:
Well, okay. It's obvious the last time you used the authentication system, and you gave a couple examples of authorization you're doing something like a user can update the settings or anything like that. Are there any kind of examples of when you, or you've seen other people use authorization systems where it might be something that people wouldn't have thought of to use on authorization? I know I didn't prep you for this question, but I just want to see if you have any, is there anything that you kind of feel like people who aren't super familiar with authorization, it might help their brains to think about? Or is it more kind of like once you get it, you get it?

Joseph Silber:
I mean, it's important for people to understand that these two concepts of authorization there's authorization that is connected to a section of your app, like you said, settings, or a dashboard or some sort of, and then there's authorization for individual specific entities within your application. So again, you can have very broad abilities or very narrow abilities, depending on what you need. Sometimes people learn one way and they think that either the default documentation, when you read Laravel's documentation says edit settings. I think that's something like that. Or access dashboard that is-

Matt Stauffer:
Something global.

Joseph Silber:
Yeah. Something global. So people think that that's what authorization is all about and they don't realize that you could get really granular depending on what you need.

Matt Stauffer:
Yeah. I like that. And one note to everybody, one of the cool things about having a global system like this that has the level of fine-grained nuance that it does, you can see an example of what it's like to do authorization and use hook and Laravel's authorization really well. If you use Laravel Nova, and I'm not saying you have to use Nova, but Nova has a pattern that is fascinating where the user interface changes in so many ways, so significantly based on minor nuances of the policies. And so, for example, in Nova, if you have given permission for an individual user to, I think they call it sea resources, something like that. It's like an extra policy item, that defines whether or not that resource will even show up in their nav bar. But then once you get into that, enter in the nav bar, let's say the blog posts section, you also can now define whether every single given entry on there will even show up at all with view.

Matt Stauffer:
You can define whether or not they're capable of seeing a list of them. You can also on an individual and you can define whether they can edit it or delete it. And Nova reads those permissions and defines whether or not there's an edit button and defines whether or not there's a delete button. And when you click on it to view it, are there some of the more advanced tools there or are you just seeing a really rudimentary version of it? And so that's, I think the most interesting thing for me there is that there's a pattern for us all to consider, which is we can build additional tooling and user interface and stuff like that, on top of this really rudimentary question of can cannot. Using the idea that you're saying where you've got those blade templates that are just in line saying, should this person even see a delete button for this individual blog post? Sometimes it's going to be the whole page, but sometimes going to be just one blog post. I really appreciate you bringing that up.

Joseph Silber:
Yeah. That's a very good example. And the way to do it is really smart because you don't have separate permissions to edit and a separate permission to show the edit button. They automatically figure it out based on the permissions you have, if you are allowed to edit it only then do they show you the edit button?

Matt Stauffer:
Yeah. And just like you were saying with the nav for the edit settings. So yeah, definitely see that for an inspiration. So one of the questions I'd love to ask folks, and these ones says, what are some times where either this system has tripped you up or what are some common challenges that you see people running into when it comes to authentication and authorization?

Joseph Silber:
So this is really, I mean, authentication, probably every app has authentication at some point. And that encompasses a very huge part of every app. So depending on how big your app is and what you're doing, for example, one of the things that people used to struggle with a lot is people that have both an SPA. SPA stands for a single page application. So people build single page applications that talk to the backend and the easiest way to get started this probably with cookie based authentication like we said before. So, but then they want to build an API and API is a stateless and they have, let's say mobile app that wants to talk to the API. And now the API usually use works with token based authentication and they want to use both in their app and it gets quite tricky. So this used to be very tricky, I should say because-

Matt Stauffer:
Yes. Because now it's not.

Joseph Silber:
Yeah, because there's not a core package maintained by Laravel core team called Sanctum. It used to be called, what was it called? They changed it.

Matt Stauffer:
Airlock, I think?

Joseph Silber:
Airlock. Yeah. Then there was some sort of trademark issues some Swiss company and they had to change it to Sanctum. It happens. So Sanctum is a first party package that you can install that seamlessly makes both a cookie-based authentication and token-based authentication work within the same app. So if that's something you've been struggling with, look up Sanctum, that's going to help you.

Matt Stauffer:
Yeah. And for clarity, that's most going to be helpful when you're accessing the same routes from both. Whereas if you had a normal web app that's accessible by a cookie-based authentication and then an entirely separate API, that's only accessed by the API. It's no big deal, but if you've got JavaScript components that are authenticating themselves based on your cookie that also need to hit those routes, that's when you start kind of getting into those questions. And there's not a default way in a lot of non-Laravel spaces to even think about how to do that. And I remember definitely like Adam asking people on his podcast, "So how do you actually handle this sort of authentication?" And people are like, "Ah." So yeah, Sanctum is brilliant and beautiful for us.

Joseph Silber:
Yeah. So just to be clear, you're right, that this whole issue only arises if you're using the exact same routes for both, but let's just be clear what you would do if you're using separate routes. So we haven't even touched really about how authentication works. Maybe we should go back to that.

Matt Stauffer:
Yeah probably. Yeah.

Joseph Silber:
So back to our simple cookie based authentication. So what happens is you put in a username and password, and I guess at some point you're registered as a user.

Matt Stauffer:
In theory. Yeah.

Joseph Silber:
Yeah. In theory, we're going to get back to that soon. So you registered as a user and now your username and password is stored in the database. Obviously your password is hashed. Should we get into that?

Matt Stauffer:
Yeah. Just real quick, what kind of hashing is it and how do I know that you're not just storing my password in plain text.

Joseph Silber:
Or why shouldn't I?

Matt Stauffer:
Yeah. Oh, why shouldn't you? There's that too. I guess you could start there.

Joseph Silber:
Yes. So the very first thing I could say about authentication is never try to hand roll it. People try to write their own thing. There are too many got yous and too many security issues that can arise. Laravel has been around for years. It's been battle tested. I mean, Laravel actually has had some minor security issues and they're patched right away. And the whole community is notified about it. So Laravel is really on top of their game when it comes to security. Never, ever attempt to write your own authentication.

Matt Stauffer:
Amen. Amen. Amen.

Joseph Silber:
Unless you're Facebook or Google.

Matt Stauffer:
Yeah.

Joseph Silber:
So hashing, the idea of hashing is that you never want to store people's passwords directly in your database as plain text. And the reason for that is that unfortunately people reuse their passwords everywhere. So if you have a little thing that you don't really care much about it, you're not really securing your server that much. People are going to use their password that they use for the bank account and they're going to use that on your app. If one day your app is hacked and people get access to your database, they're going to have a whole slew of usernames and passwords that they could just try and all around they're going to go to Facebook, they're going to go to Google, they're going to Chase, to TD, to anywhere they can go. And they're going to try to log in. So that is why you never ever want to store your users' passwords in your database.

Joseph Silber:
However, if you don't store their password, how do you know later on when they're logging in? How can you identify them? So the answer to that is hashing and hashing is some sort of mathematical algorithm where you can take a piece of text and you run it through the algorithm. And what you get out of the other end is a whole bunch of gibberish that doesn't mean anything. The only guarantee you have about that gibberish is every time you run through a piece of text through that hashing algorithm, you're going to get the exact same gibberish. Crucially, there is no way to get back from the gibberish to the original text. So if somebody hacks a database and they find that gibberish in your database, there's no way for them to find the original password.

Joseph Silber:
So hashing means when you register and you create a new password, Laravel is going to run that password through a hashing algorithm. And it's going to store that hash in the database. Then when you try to log in and you log in with a password, you're obviously writing your password in plain text. But when Laravel tries to log you in, it's going to take that password, run it through the hashing algorithm again. And then it's going to check whether that hash matches what's in the database. It gets more complicated with salt and actually pepper. Laravel doesn't use pepper.

Matt Stauffer:
I was going to say I don't even know about pepper, sheesh.

Joseph Silber:
So just in short. Salt is another piece of text that is added onto the hash. And pepper is a token that you can keep in your app. Do we want to get into that?

Matt Stauffer:
No, but let's talk about salt real quick. So there is a salt that's used in hashing, which is the, I always forget which the app key is and isn't used for, so much that that-

Joseph Silber:
The app key is only used for encryption not hashing.

Matt Stauffer:
For encryption. Yeah. So-

Joseph Silber:
So the idea-

Matt Stauffer:
Go ahead. Go ahead.

Joseph Silber:
Okay. So one of the problems with the hashing doesn't solve is what's called the rainbow attack. And a rainbow attack means that if somebody gets access to your database and they have a list of usernames and passwords, now, even if the passwords are hashed, they have an easy way to get back to the original password. And the reason for that is because people aren't careful and the same type of people that use their passwords for the bank account and for your app are the type of people that use a password, one, two, three, four. So what these hackers have learned many years ago, I mean, the industry has moved on from that, but what they've learned many years ago is that they can compile a rainbow table, which basically takes all the common passwords and hashes them.

Joseph Silber:
So you take, let's say one, two, four is a common password. You take one, two, three, four, you pass it through the hashing algorithm. And now you have a string that if you ever find the string in a hack database, you know that they had that password originally. And then you can try that password in the bank. And you can find the top million passwords, store them on a rainbow table and it's very easy to look them up.

Joseph Silber:
So yeah. So to mitigate that, Laravel uses something called a salt. A salt is just a random string of numbers or characters that is added onto your plain text password. So let's say your plain text password was one, two, three, four. Please don't, but if it were. Now Laravel is going to generate a complex piece of random text. Let's say, I'm just looking at my keyboard. Let's say POI, okay, it's going to be more complex than that, but let's say it says it does POI and then it has a dollar sign. Not that it matters, but it's going to POI on one side and then one, two, three, four on the other side and hash it. Now it's going to take the resulting hash. And it's going to add onto the resulting hash of gibberish. It's going to add on to the beginning of that gibberish, that POI that we said the salt. So that there's a key that is both available in the resulting hash value and that is fed into the original text.

Matt Stauffer:
Oh, that's how it works.

Joseph Silber:
Now-

Matt Stauffer:
And it's different for each one. Right?

Joseph Silber:
It's different for each one, but it's stored within the database. So when it's in the database, you can get that first part, which is the salt. So that's why-

Matt Stauffer:
Everything before the dollar sign, basically.

Joseph Silber:
Yes. So even with hashing, once you hash the password as salt, there's no way to look it up in the database. So Laravel can't query the database. Find me a user with this username and this password. There's no way to do that. It has to find the user by username. Once it has it, it can look at the hash, take out the salt key, concatenate the salt key together with a plain text hash, run it through the hashing algorithm, and then compare it. And that's-

Matt Stauffer:
And I know that you got this, but I want to make sure that people hear what he meant was concatenate that key with the plain text password and then hash that, and then compare it against the... Yeah.

Joseph Silber:
Yes.

Matt Stauffer:
Totally

Joseph Silber:
And that is salt. Pepper, if you want to talk about it. Laravel, doesn't use pepper about the pepper is when in addition to all this, you also have a secret key, like if we would be using the app key on top of that. So that if somebody hacks your database, but doesn't have access to your actual application, then that gives it another layer of security, but that's really rare. And that also means that if you ever lose your app key, then all of your users accounts are locked out.

Matt Stauffer:
Or if you ever have reset your app key then you have to...

Joseph Silber:
That's why Laravel doesn't use it.

Matt Stauffer:
Yeah. And if you're curious about this whole thing, I remember that I got confused about this so often about what app key was and wasn't used for. That I had some folks at Titan, I think primarily Jake Beckman, write an article called app key in you or something. I'll link it in the show notes. So, but what Joseph said is definitely true, which is that if you're thinking about cycling your app key, the number one thing that you need to think about is encrypted and decrypted, encrypted data in the database, basically, which is not this. Encrypted and hash are not the same thing. So but a question about that. So why we use all this fancy stuff? Why don't we just use MD5?

Joseph Silber:
Oh, so-

Matt Stauffer:
For the old heads in the audience.

Joseph Silber:
Well maybe hashing is MD5, we haven't mentioned that. So MD5 is way too fast. What you want with a hashing algorithm is two things. Number one, that you want it to be single directional, you want it to only be able to go from the plain text to the hash. And that's from the hash back to the plain text. That is one thing. And the other thing is you want it to take it a while. And that is-

Matt Stauffer:
Which is crazy. Yeah. It takes a while to get that. So explain that if you don't mind.

Joseph Silber:
So everything we do in computers, we're trying to make them faster and faster and faster with the exception of hashing. And the reason for that is because if you actually do want to... If somebody hacked into your database and they found the list of usernames and passwords, even though they have no way of going backwards from the hash to the plain text password, they can still cycle through all the passwords in the world and try to create that hash and see if it matches. So they could do, let's say, in our example, before we had a salt of POI, the salt is readily available. That's part of the resulting hash that is stored in the database. So they could do POI, add on a dollar sign, then add any password, let's say P-A-S-S-W-O-R-D. That's a very popular password. Unfortunately.

Joseph Silber:
So they do that and they run into the hashing algorithm and they see if it matches the hash, if it doesn't, they move on to the next one. So instead of a rainbow attack, what they're going to do is actually going to spin through all of the popular passwords with this particular salt. So they can look it put up in general-

Matt Stauffer:
Set a smarter version.

Joseph Silber:
Yeah. So, and computers are very cheap these days. And cloud computing is very cheap and NVIDIA will sell you a graphics card that could do millions of these in seconds. So what you want to do is you actually want to make the hashing algorithm you use, you want to make it as long as hot as possible and take as long as possible without actually affecting a user experience. You want it to be short enough so that a single hashing algorithm, when you log in and only have to hash a single one should be fast enough. But if you want to hash a bunch of them, it should take you a good couple of years. So that is what we're doing. And Laravel gives us all of this for free without, you don't even have to know all this. We're just sharing this with you.

Matt Stauffer:
Yeah. And if you do want a super nerd out about this. Laravel uses a method called bcrypt, and you can learn a whole ton more about that, but something that was added recently, which is really cool. And I don't know if you were involved in this, is the ability to define how many rounds it's using. And basically that's just how long it's going to take to run every time. And so there's an environment variable. And again, I'll link to it in the show notes that basically allows you to define that. It sets default to 10, but if you're worried saying, "Oh, well, what if ours isn't secure enough? Or what if these passwords need to last for the next 10 years and processes are going to go a lot faster?" You can always amp it up if you want, so.

Joseph Silber:
Yeah. But unless you are a bank, you probably shouldn't worry about it.

Matt Stauffer:
Exactly. Yeah, you shouldn't. Yeah. But just for those people, you bankers or future bankers, I love that. That is so helpful.

Joseph Silber:
Yeah. Just because I'm paranoid doesn't mean they're not after me.

Matt Stauffer:
Yeah, exactly. So before we move on to just kind of like what's other topics, things or topic, are there any other common challenges or got yous that you think that make people get stuck on learning authentication or authorization?

Joseph Silber:
Okay. So first of, which is very important that you had started this podcast with is never to confuse authentication with authorization. And just to confuse people, the HTTP spec, I don't know if they set out to confuse people, but the HTTP response for unauthenticated users is 401.

Matt Stauffer:
Yeah. Not authorized.

Joseph Silber:
The HTTP response for unauthorized is 403. But the names for these responses for these HTTP status codes are confusing because 401 is 401 unauthorized, even though it is response for unauthenticated. And 403 is forbidden, which actually does make sense, but 401 unauthorized means you're not authenticated.

Matt Stauffer:
Yep. Which it's funny because if you're not authenticated, you're sort of not authorized because you're assuming that you're hitting a route that has authorization requiring you to be at least authenticated, which is interesting because an authorization... And sorry, just to go on a nerd tangent. Authorization could include directives around what guests can do. So in theory, you could be unauthenticated and still-

Joseph Silber:
That was added to Laravel recently.

Matt Stauffer:
Oh yeah. Okay, cool.

Joseph Silber:
Laravel six or seven added the ability to define policies for guests.

Matt Stauffer:
Love it. I love it. Thank you for bringing that up. But even if it hadn't, the idea, it's just important to know that an unauthenticated user, AKA a guest can be authorized or not authorized to do certain things. And so authorization is actually impacted by authentication, but it's not entirely dependent on authentication. Now, if you have no authentication at all, of course, how are you going to differentiate between one person and the other? Now, theoretically, you could do it based on other crazy things like their IP address or whatever. But in general, authorization is primarily about guest versus users and then most importantly is about users versus other users based on other factors. But I think it's helpful to your example the 401. In theory 401 saying you're not authorized, could make sense, but what they really meant was you're not authenticated, so.

Joseph Silber:
Yeah. It's important for like, these are conventions that are used throughout the industry. And if you stick with the conventions is going to be so much easier. For example, if you have a front end-

Matt Stauffer:
Amen. Yeah. Sorry, go ahead.

Joseph Silber:
If you have an SPA, your front end is talking to the back and then you get back a 403, then what are you going to do? You're just not authorized to do it. If you get back a 401, chances are you're going to show up a nice modal and ask the user to log in again. So you want to stick to these and again, Laravel just makes it so easy, whatever you do, they are going to return the correct response for you. By the way, sometimes when something isn't authorized, people actually return a 404. And that is because you don't want to leak that something exists. For example, if you GitHub, if you go to GitHub, you have a private repository, you're not logged in. You go to that repository page, they're going to serve you up a 404. It's quite confusing. I mean, about a year ago they started actually saying 404 not found, do you maybe have to log in?

Matt Stauffer:
Yeah. So to give you that clue that that's, yeah.

Joseph Silber:
But the-

Matt Stauffer:
We've gone back and forth on that a million times in certain circumstances because we know the thing exists and we know that we want to give you the more correct error, but sometimes the more correct error is not the most appropriate as you're describing here, so.

Joseph Silber:
Yeah. Another thing that trips up many people is that sessions aren't available in controller constructors. So the reason for that we can get into soon, but the main idea is if you want to get the current user, we haven't even touched on that. How do you even get the current user? How do you interact with the current user?

Matt Stauffer:
Jeez, let's talk about that, Joseph. 59 minutes in or whatever.

Joseph Silber:
Yeah, there's so much to talk about.

Matt Stauffer:
Yeah. No kidding.

Joseph Silber:
I don't even know where to start. Okay. So once you're logged in, how do you log in? So the way you log in, you can either do it manually. The auth facade has an attempt method, auth attempt that lets you try to log in, you pass it into credentials that the user has sent you and that's how you log in. Once the user's logged in. Now they're in the session, like you said before. Happens to be, you don't have to do all this manually because like we said, we didn't even talk about presets. There's so much to talk about. How long are we going for it?

Matt Stauffer:
Well, the good news is the presets is going to be an entirely separate episode. So we could just say there are presets. And if you do the presets with make auth, which I think if you don't know what you're doing, just do that. Do a preset with make auth or dash dash auth or the most common the current one is, you will get all the authentication stuff built in. If you just spin up a new layer overlap and you're wondering all these things are, where these things are we're talking about. We're not implying you need to build it yourself. It's just an option you have to turn on. So let's just assume anybody we're talking to here has auth already created.

Joseph Silber:
So when you have auth already created again. You can do it with Laravel, has a package sort of it's called Laravel/UI. And that also gives you all the UI and points for logging in for registering forgot password, reset password. It's insane what Laravel shifts with.

Matt Stauffer:
And the templates too, right?

Joseph Silber:
Yes.

Matt Stauffer:
It's the routes it's the controllers, the templates, everything.

Matt Stauffer:
Just a quick note. Since we recorded this podcast, Laracon Online happened. Taylor announced Jetstream and Laravel 8. And we will talk all about Jetstream in the next episode with Michael Dorinda. So don't worry about that. We weren't talking about that when we recorded this, but you'll get to it next week or two weeks from now.

Joseph Silber:
Yes, you can basically just all this boilerplate that every single app needs, you can just focus on what your app does and you just off to the races.

Matt Stauffer:
Preach.

Joseph Silber:
Okay. So assuming you registered then assuming you logged in, what now? So when you want to protect your route, there are many different ways to protect your route. One of them is through middleware and we know what middleware is?

Matt Stauffer:
We have not. I'm looking at my watch as if it's going to tell me, I don't think we've done middleware yet. No, I'll let you go. Because I bet you have proven very effective at communicating things simply. Can you tell us the 30 seconds, the five seconds version of middleware?

Joseph Silber:
Well, I don't know if I'm up to that challenge.

Matt Stauffer:
Okay, well I did this one of my book, a couple of times, so middleware is basically classes where you could imagine like, so in PHP and again, we'll have a middleware episode later. But in PHP and things like Laravel when you get the request coming in from the browser, it creates a PHP class that kind of represents that request. It's called the request object and it gets passed in your Laravel app. And then Laravel spits out a response object, which then is passed out to your browser, which is rendered into basically your HTML and your headers and stuff like that. But sometimes you want to kind of put a rapper like that incoming request should kind of pass through a little bit of a bubble that does something or check something or validate something before you actually get in your application. Or it should pass through another bubble that maybe decorates something or whatever else on the way out of your application.

Matt Stauffer:
And so it's kind of like a way to say these are like... It's like the city walls a little bit, but you're not protecting, you're maybe checking or guarding whatever. So anyway, as every request comes in, it kind of goes through your middlewares all of them, both the built in Laravel's ones and also any customs one you added. And then it hits the app and then the app, which is like your routes and your controllers, whatever else does its work. But then when you return something at the end of you or response to whatever else, it goes back through those same middlewares. But in the opposite order, before it actually goes out to the end. So middlewares are basically the way for you to do the most global things. Yeah, I think that's the best 30 second version I can give. So there's a middleware that has to do with auth. Tell us a little a bit about it.

Joseph Silber:
Okay. Yeah. So you explained it very well in detail. In short, what I would say middleware is it lets you hook into every request before it hits the controller. You can do whatever you want with it. And when the controller returns response, you could also intercept it and do whatever you want.

Matt Stauffer:
Perfect. Much simpler.

Joseph Silber:
So. Yeah, you explained that in more detail how it technically works. Every, every piece of middleware in Laravel is a class and that class can do something with a request. It gets handled a request and it returns a response. So authentication is a built in Laravel middleware. If you assign that middleware to a route, we'll get to a minute how we do that, then the request is going to pass through that middleware before it even hits your controller. And it's going to check if the user's currently logged in. If the user is logged in, then it's just going to continue on its way and hit your controller like it always does.

Joseph Silber:
But if it doesn't, your control is never going to be a hit. So your control doesn't even have to bother itself with authentication. Your control it can always assume that there's a user ready there to be used. And the middleware is smart enough that it's not just going to return a 401. It's going to check if it's an Ajax request, then it returns a 401. If it's not an Ajax request, if it's a regular request, then it's going to redirect the user to the login page. And again, all of this, you get for free by sticking to conventions and using what Laravel ships with, it's just easier, trust me.

Matt Stauffer:
Yeah. And if you're going to want to put that middleware and you've probably seen it somewhere in the basic code, but basically you're going to rap either you're going to add it to a single route or more likely you're going to wrap a whole bunch of groups with a route group or a whole bunch of routes in your route group. And that route group is going to say something like middleware arrow auth or something like that. And that auth string A-U-T-H is a shortcut that points to that class. And it's bound in the HTTP kernel, but that shortcut passes to Laravel the understanding that that particular route or that group of routes should all be basically wrapped with this middleware. And then if you're curious, you can go look up what is off point to, well, it points to the redirect if authenticated.PHP, right? And you go look that up and there's another one, there's guest as well, which is basically the inverse, right?

Joseph Silber:
Yes. So guest ensures that the user is actually not logged in. So for example, if you have a login page and I'm already logged in and I somehow hit that page, you want to redirect me, I guess to that homepage or whatever. So you just can do if auth guest then just redirect there and you're done. I just love these names. I don't know where they get these names every, as much as possible all methods in Laravel are usually single word. I don't know if you remember back in the day when Taylor released Laravel 4, we went from Laravel 3 to Laravel 4. There were some breaking changes, none that many. One of the changes was that we used to have methods would be snake cased, not the camel cased, just like functions are. But since we switched to PSR, which PSR is it? I don't know which one, the PSR that's-

Matt Stauffer:
It might've been two, but I'm not sure.

Joseph Silber:
Yeah. I don't remember now, but one of the PSRs that's about the syntax. It says that basically it's stipulates that functions on standalone functions or snake cased methods are all camel cased. So all methods in Laravel switched from snake case to camel case. You know how many breaking changes that mean? Almost none because all of the methods had single words and that's it. And to come up with single words that are intuitive and you look at it and you understand that that is super genius. I mean, I think that's Taylor's biggest power just writing good API. Program or APIs.

Matt Stauffer:
Yeah. I think it's one of his undersung powers as well. I think that people can look at architecture decisions, whatever, and those things are all great. But it's the ability to like you said, not know what something does and look at the name and say, "I understand what it does now."

Joseph Silber:
Yeah. I think that's the second biggest power, for us biggest power is writing staggered comments.

Matt Stauffer:
That I don't even know if that's a power, that's an alien something. I don't even know what that is. Because that's-

Joseph Silber:
Do you want to quickly say what that is?

Matt Stauffer:
Yeah. Yeah. Go ahead.

Joseph Silber:
So all comments to Laravel code are three lines and the length of each line is three characters less than the line above it. And whenever you look at a class that has a bunch of comments, it's just visually pleasing. You look at it and there's this sort of, it's like it's symmetry because it's not symmetrical, but it's just, it's nice to look at. And just how I got that bug too. I mean, Taylor affected me and all of my coders commented like that.

Matt Stauffer:
I love it.

Joseph Silber:
I will never forgive him. You know how much time I've wasted on it? I don't know how long it takes him.

Matt Stauffer:
It's funny because I just recently introduced kind of an old school PHP programmer to Laravel who super wasn't familiar with it. And he's just saying, he had a certain complaints and I was like, "Oh no, no, no, no, no. Those things that you don't like, you actually are absolutely going to love when I point how it actually works out to you." And I would show something to him. He go, "Oh wow. That's exactly how I want it. Or that's really great." And one of the things, I can't remember what it was, but he said something and I was like, "Oh, that complaint you have, or that personality trait you have, whatever, you would love to see these comments." And so I just took them over and I showed him and I was like, "Just take a look at this." And he's like, "This is freaking amazing." He's just like, "I had no idea this was here all along." So yeah. It's like one of those hidden secrets.

Joseph Silber:
Yeah. So for example, if somebody hits a route and they're not authenticated, what's going to happen is they're going to be redirected to the login page. After they log in, you want to redirect them back to where they wanted to go. So obviously the redirector class has a method with a single name that returns them there. I wouldn't have come up with it, but it's called intended. So you could do return, redirect intended. And that's what ends up and all of this happens automatically.

Matt Stauffer:
Yeah. It's freaking magic.

Joseph Silber:
Yep.

Matt Stauffer:
Okay, so you-

Joseph Silber:
So, back to-

Matt Stauffer:
Go ahead.

Joseph Silber:
We're still getting to constructors.

Matt Stauffer:
Exactly. Go ahead.

Joseph Silber:
So, middleware lets you add functionality that intercepts the request or the response. We're mainly talking about intercepting the request there, but it works with the same mechanism. So if you want to, like you said, if you want to restrict access to a whole bunch of routes to users that are signed in, you do route::middleware, and you pass it a string of auth, which like you said, is a shortcut registered in HTTP kernel. And then within that group, all the routes in that group are going to be restricted to only logged in users. And if they're not logged in, they're going to be redirected back and forth like I said before. And the same goes for authorization. So authorization also has, there's a built-in middleware authorization called CAM C-A-M.

Matt Stauffer:
Surprise.

Joseph Silber:
Yeah. So if you're doing simple abilities such as edit settings, then it's quite simple what you do, you do can: and that's how you... In the string, the way you pass middleware is you pass the name in the middleware as a string. And if you want to pass arguments to the middleware, you pass it as part of that same string separated by a colon. And then if you have multiple arguments, each argument is separated by a comma, but everything within that string. So for example, if you want to restrict the section to only users that can edit settings, that was the original example. You would do middleware and pass the string can:edit-settings. And that would be the whole string. What that would do is it would call the middleware with the string edit settings. And that will be the ability that is checked at the gate.

Joseph Silber:
So again, everything works together. And if the user is not authorized to edit settings, they're just going to get a 403 response. Otherwise they're just going to keep on going on their merry way. So that's the story for simple abilities, but then we have model abilities and it gets a little trickier. So before we can talk about model abilities, we should probably talk about route model binding. Have we covered that ever?

Matt Stauffer:
We haven't.

Joseph Silber:
Have we covered routes?

Matt Stauffer:
Routes, I feel like we already did the routing one because I think that was Caleb. So I think we just didn't talk about it. Totally missed it. So let's just do it here because it's not going to get covered somewhere else.

Joseph Silber:
Okay. So let's just do go quickly. If we have a route that's post/whatever the idea of that route is so maybe-

Matt Stauffer:
45.

Joseph Silber:
45. Exactly. But 45 is a variable. It's not static. If you want to see a list of posts, you go to slash posts. So in your routes, you're going to have a string route::gate and in get, you're going to have posts and that posts routes you someplace. But what if you want to get a specific post? That's going to be post/whatever posts you're looking for. So that's going to be the ID. So Laravel has this syntax for a placeholder within that string. So you could do post/{post}. That post will then be internally available to you within the controller method. You're going to be able to access that on the request. You're going to be able to get from the request, the parameters, that's going to be a parameter to the request that's called post. Now by default, what's going to happen usually is that you're just going to get it off the request.

Joseph Silber:
But what do you want to do with that? It's an idea of a post ID itself doesn't serve you much. What you want to do is probably look it up in the database. So what you can do is you can accept a parameter called post in your method. You type into it with a post model. And Laravel automatically figures out that what you actually want, is that specific post with that specific ID. And if they're named the same, you could do that explicitly to my wire them up, but implicit route model bonding is if the name of that placeholder within the route matches the name of the argument that is being passed into your method. If the two match up, then Laravel is behind the scenes automatically go up to fetch that record from the database and inject it into your method so that when you get that method, you can right away... Again, these are more and more steps that are just eliminated from here you just get to focus on your app.

Matt Stauffer:
You got your model all ready. You don't have to look it up. Yeah, go ahead.

Joseph Silber:
Yeah. Not only that. What if the model isn't found? The model doesn't exist. You probably want to return a 404. That's already handled for you. Everything is handled for you. Now, back in the day, I think it was Laravel 5.2, people were running into issues with this because they have their middleware bounds. And what happens is route model binding fetches the entity from the database. Now people were doing some sort of authorization checks in there. So people have, let's say deep, global query scopes. We covered that?

Matt Stauffer:
Not yet. Nope. No wait, we covered them, but we covered them pretty simply. So remember-

Joseph Silber:
But basically-

Matt Stauffer:
Go ahead.

Joseph Silber:
Basically it's a way to tell eloquent that every time I fetch something from the database, add certain constraints. That's one of the-

Matt Stauffer:
I remember so when Jonathan Renick was talking about the global query scopes, he said the local scopes are the ones where you actually modify it when you need it. So you can say post arrow publish, or post arrow unpublished. The global query scopes are one that are getting added every single time you request a list of posts, regardless of whether you've chained on that thing or not.

Joseph Silber:
Yes. So what people were doing is that for example, people wanted, like we said before, example, imagine you have a list of blog posts and every blog post has an author ID. Now, when you fetch all of these whenever you fetch a model from the database, people wanted to restrict it to where the author ID is equals to the current user ID. And how do you get the current user ID? You just do auth::ID. That's simple. So what people were doing is they were adding a global scope that said where author ID is equal to auth ID. And the problem with that was that in order to do that, you need a session to already be primed. You already need to know who the current user is before and the route leaves a little on top of the stack because the route is resolved first.

Joseph Silber:
So in Laravel 5.3 Taylor reworked the hallway middleware are stacked. So what happens now is that authorization is not available. The session is not available within the controller constructor. People were doing all tidy within the controller constructor also, and that's no longer available. So what was added is you can now do middleware directly within the controller constructor. So instead of if you need the current user and you want to do authorization, instead of doing authorization yourself within the controller constructor, you can do this authorize.

Joseph Silber:
Or the best thing, even as you could do this authorized resource where you authorize a full resource, resource controller has seven methods store, create view, update, delete all of these methods. You can do this arrow authorized resource and you pass it just a model of the string of a model. Either you do the model::class or you pass it the whole namespace, and then behind the scenes, whenever Laravel tries to route any routes to any of these methods, it is automatically going to run the authorization beforehand. And again, it's going through a return of 403, if it's not there. So yeah, it was a little tangent and maybe it was more detailed than was necessary, but-

Matt Stauffer:
It's still good.

Joseph Silber:
... That's a little history. You can either do can, if you do the can, if you do the middleware on the routes and you do can and you pass can first you pass it the name of the ability. And then you can also pass it either. For example, if you want to do can create posts, you do cancreate,app/post. And that means you want to know the second parameter that you pass to the can middleware is the type of the model. So that will check if they can create posts in general, how would you do that if you want to know whether they can update a given post? So what you do is what you pass as the second parameter to the CAM middleware is actually the name of the placeholder in the routes. This is magic, but it all gets wired up together.

Joseph Silber:
So you have a route called posts/{post} so post is now the placeholder for the ID, but not for the ID because we're using implicit route model binding, that ID is going to be replaced with the actual post. So when you were doing later on can:update,post. Instead of using the post, the middleware is going to get the actual post entity, the actual post model from the request. And it's going to authorize It against that. If that's not magic, I don't know what it is.

Matt Stauffer:
So if anyone didn't totally follow, if you were to create a middleware on a route, or if you were to apply a middleware in a route, and that middleware said, can:edit,. And then the name of a placeholder that was in that route definition. So again, if that route definition was /post/{post}. Then now you have that word post as your placeholder, you can then say, can:edit,post. And the gate is going to be checked by that middleware. So the middleware is going to go to the gate and say, can current user edit,. And then the post that basically would come from taking the ID that came in from the URL and then looking up, find or fail for that particular post. And then it passes it into the gate for you. And if that fails, then you end up getting a 403 returned.

Matt Stauffer:
So all that work that seems very natural and normal to do all the time. You don't even have to do. And that's why we're just sitting here doing a little happy dance with this thing is because it's just more stuff that you always probably will want to do is you're thinking about this that you no longer have to do.

Joseph Silber:
So let's talk about more things that just come for free and we don't have to do. Rate-limiting, throttling. If you worried about security, one of the things you want to make sure is that your log in route is protected by rate-limiting. You don't want people trying to user names and passwords all night until they find something. They're probably not going to do it by hand, but if they keep going, they might find by luck somebody's username and password.

Joseph Silber:
So throttling or rate-limiting means that you only allow a given amount of requests let's say per minute, from any IP address. Now this can get quite tricky and you have to figure out on a rolling basis how many times they've already tried and you have to find a place in the cache to store it. All of this is handled automatically for you by Laravel, if you use the scaffolding and you have a logging controller. That is automatically going to do the rate-limiting for you and you don't have to worry about that.

Matt Stauffer:
Yeah. Which is amazing. And if you do end up needing that kind of rate-limiting, those tools are available for you to use somewhere else. You can pull Laravel's rate limiter and rate someone else. But again, if you use the scaffold, you just get these rate-limiting for free. You just, you don't even have to think about it.

Joseph Silber:
Yeah, everything in Laravel is built on layers. You have the small building blocks that are available to you if you want to use them, then there's multiple layers on top of that that simplify it more and more and more until you get to the top where as they say, Laravel is an application that comes with the batteries included, everything works out of the backs. As you start using it more and you have more complex needs, you can tweak it and change it according to your needs.

Matt Stauffer:
Yeah. Yeah. That's good.

Joseph Silber:
Another thing recently added was password confirmation. You know how sometimes even if you're already logged in and you want to do something dangerous, for example I think GitHub again, uses it. If you delete a repository or maybe if you add a billing or-

Matt Stauffer:
They definitely use it, if you add like add users to your account and stuff like that, like paid users. So yeah. That would be editing billing. Yeah.

Joseph Silber:
So if somebody does something either very destructive, or something very sensitive, you might want to make sure they didn't just log into some kiosk and walked away and somebody else is trying to do something. You want to, once again, make sure that it's actually the person that originally logged in. So Laravel added a password confirmation middleware lately, where if you do that, it's going to ask the user to log in again, it's going to give you use the password. And I think the default, it's like three hours, I think, and for three hours, it's not going to ask it again, but that is another layer of security that you can get and to handle this by hand all of this together will take you years.

Matt Stauffer:
And then of course you also get password resets and you also get password or email confirmation when you first sign up. And I'm sure there's a million other things that you get-

Joseph Silber:
And logging out of all the devices, which is also, I think, a recent edition. If people are logged into multiple devices and they want to log out so you can log them out from all other devices. That is also amazing.

Matt Stauffer:
Yeah. Yeah. There's just, yeah. As people who had to write this from hand before, by hand, before, back in the CodeIgniter days and other days, like we can recognize just how incredible this stuff is and it just keeps growing.

Joseph Silber:
Yeah. I just love when each new release of Laravel, I can rip out a bunch of my custom code and just replace it with whatever comes with the framework. That's like the best feeling.

Matt Stauffer:
I totally agree. And that should be a goal for all of us. Just y'all know sometimes I have to, I think share with people just the value of doing things the Laravel way. Because not only is that no longer code that you have to maintain, or you have to be the responsible for being the expert in like you were talking about, but it's also code that will likely work better together with future things that are released. And if the more the Laravel authorization system and authentication system you're using, the more likely that a new cool feature will come out and you could just get it for free. Right. And the more you're doing your own stuff, the more you will have to rewrite that thing for free later, if you want to. So.

Joseph Silber:
Yeah. The ultimate goal is not to be writing any code whatsoever.

Matt Stauffer:
Yes, exactly. Just let the robots do it all and kick back and hardship or whatever it's going to be. So okay. So since we're coming short on time, we haven't covered everything, but there's one thing I realized we hadn't covered, which is how do you get the currently logged in user or the guest or the auth methods and the office, stuff like that. So what are kind of the most important things that you use day to day on either the global auth helper or the auth facade?

Joseph Silber:
So the auth helper and the auth facade both point at the same thing, you either do auth(:) or you do capital A Auth:: But then you have to make sure to either import it or namespace it. And then you can get either you can do with ::user, which gives you the currently logged in user. You can do a check, which is going to give you a Boolean of whether a user is logged in or not. You can do guests to know the inverse of that.

Matt Stauffer:
The opposite.

Joseph Silber:
Or you can do ID sometimes if you want the user ID, if you're going to do off arrow user arrow ID, if nobody's logged in and the user actually returns null, that's going to tell an error. So there's a small shortcut. You can do auth ID, which gives you back the ID directly. And then you can use that however you want. But honestly, I don't interact with that so frequently because these are all, like you said before, all the wiring is in place to handle that for you, you just set up your middleware, you just set up everything you need. And that's it. Maybe I use it sometimes in global query scopes where when people create models, I want to know who created them. So I have some sort of global middleware, or even maybe a creating event that, you know how you can do events in Laravel when in eloquent, when you create a new model, you can set additional attributes onto it.

Joseph Silber:
Yeah. So then you attach to your author, but yeah, besides for that, I don't really find myself interacting with these directly that much, because like I said, everything is wired up.

Matt Stauffer:
Yeah. I mean, occasionally I do like if there's a settings page. Sometimes I will directly modify the results of their saving the settings page on the auth user object itself. So you could do auth user update, pass an array of parameters and then that's it.

Joseph Silber:
Yeah. That's a great example. Yeah.

Matt Stauffer:
But yeah, in terms of day to day authentication and authorization things you shouldn't really have to, because those things are all hidden behind at can or whatever, all those very convenient things. If you do have the user, it is very nice to be able to say user arrow can or user arrow can or whatever, just because it's a really nicely fluent syntax for that. But again, that's not the primary way that we ended up using authorization anyway, so. Okay. So, I mean, I think there's a lot, but usually this is the point where I say, is there anything else you'd really like to talk about this topic? So that's actually a perfect transition to, are there any other really important aspects of this, obviously you and I could talk for three more hours right here. Not only because we're enjoying ourselves, but there's so much more to cover here, but if knowing that we have a limited amount of time, is there anything else just really key that we've missed?

Joseph Silber:
I don't know about key, but we have to touch on Socialite, which I tend to use a lot

Matt Stauffer:
Yeah, you want to give a quick intro to Socialite?

Joseph Silber:
Yes. So one of the methods of authentication is called OAuth. OAuth is a mechanism of using a third party ACL for your own app. And what that means is basically if you go online, you always see these signing with Google, sign in with Facebook, now, sign up with Apple or whatever. The way that works is that instead of keeping a password in your own app, you export that to a third party. So let's just take Google for example, if you want to let people log into you with Google, what you need to do is you go to Google, you register as a developer and they give you a set of keys. And without getting into it, trust me OAuth is very complicated.

Matt Stauffer:
It's very. Yeah.

Joseph Silber:
If you thought authentication is complicated, let's talk about OAuth. So you do not want to do this by hand. So Socialite is again, a first party library that you can install into your Laravel application. And that's going to let you do all these sign in with Facebook, sign in with GitHub, sign in with whatever. I think it comes with like five or six providers. And there's a community project that adds another, I don't know, a couple million, I think last count.

Matt Stauffer:
It's definitely hundreds. So.

Joseph Silber:
Yeah. So that's a great tool if you want to use some of these tools.

Matt Stauffer:
Yeah. And it is extremely complicated to do, I've done it before, by hand or with the packages that this is based on and it's exhausting. And I'm so glad you brought this up only because it is such a freaking superpower and you keep pointing out these things that it's just like, it should be this easy. Socialite is very high on that list. The simplicity, Socialite and Passport. Passport allows you to create your own OAuth server on your own. So Socialite allows you to add authentication through somebody else's OAuth server to your app. And then Passport allows you to create your own OAuth. And both of those are exhausting processes to code on your own and with Passport and Socialite, it's just so, so, so simple. So. Good call. Anything else?

Joseph Silber:
We can also mention Spark.

Matt Stauffer:
So Socialite, everything we spoke about now are like free first... I mean, everything is free here. How come?

Joseph Silber:
We have Laravel.

Matt Stauffer:
That's all I got.

Joseph Silber:
We have Sanctum. Then we have Socialite. All these tools are free, but obviously some things are paid. So Spark is also a first party package, but it's a paid package. Well worth it. And Spark is like, we spoke about Laravel UI and auth scaffolding and the UI for the auth. Spark is like the next level of that, it doesn't just do auth. It does use management, subscriptions, teams, everything you need. If you're building a SAS where you have many people that are buying stuff, that are buying services from you on a month to month basis, and they have teams and you want to handle that. Spark is like the best thing ever. You install it and it takes care of everything. It takes care of subscriptions, canceling subscriptions, changing plans, everything you could think of for SAS. Again, the boiler plate gets out of the way. So you just write the code that pertains to your specific app and the value that you produce.

Matt Stauffer:
Yup. Yeah. I love that. Spark is especially good for independent creators who care less about making sure that their admin dashboards look a certain way and more about just allowing people to use the admin dashboard. By dashboard I don't mean like Nova, it's more like the, can I edit my account? Can I create a team and pay for my team while I'm in there. All that stuff comes for free. And of course at that point, you're getting into a little bit more opinionated, right? Because they're actually defining the templates for those things and how team billing works, all that kind of stuff. So it's not as if Spark is for everybody. Because there's some people who say, well, it must work this way, team management dashboard or whatever. Okay. Then Spark might not be for you, but there's a lot of people who want to create a software as a service.

Matt Stauffer:
And again, don't want to waste all their time learning how to be the 10 millionth software as a service to learn how to handle team building. If that's you, Spark is for you. Get Spark, set it up with Spark like be willing to understand the fact that Spark has more opinions than Laravel does because it's going further. So it has to be a little bit more opinionated. But if you can go in and say, look, just in order to launch, I'm going to work with Sparks opinions. And if I need to tweak them later, I will cool. But it's going to get you up and running, so, so fast. The caveat there is if you and your whole team already know exactly how you want it all to work, you know exactly your tech stack and it's going to be react or you know exactly how those backend panels are going to work. Sometimes Spark might feel a little heavy for you. So spark is not a global recommendation, but it is an extremely powerful tool. At least for me, it's an extremely powerful tool for the people who need it.

Joseph Silber:
Yeah. Couldn't have put it better myself.

Matt Stauffer:
I love it. All right. So is there anything else we should talk about before we start wrapping it up this time?

Joseph Silber:
No, I think we covered all the basics.

Matt Stauffer:
I love it.

Joseph Silber:
And then some.

Matt Stauffer:
Yeah. So if somebody wants to learn more about authentication authorization, whether in Laravel or as a broader topic, do you have any particular articles or tutorials or resources that you'd recommend for them?

Joseph Silber:
Yeah. So you asked this of all your guests and more or less, they're all giving you the same answer because their Laravel documentation is unbelievable. The amount of effort that goes into that. I mean, there are so many open source projects out there that have amazing code and amazing functionality, but nobody uses them because they don't know how to. And the Laravel documentation is really next level.

Matt Stauffer:
Yeah. I agree.

Joseph Silber:
And add on to that Laracasts and yeah.

Matt Stauffer:
You're pretty good to go.

Joseph Silber:
Between the Laravel documentation and Laracasts, I don't think you need anything else.

Matt Stauffer:
Yeah. I'm with you on that one, for sure. All right. So personal fun moments. So we had a chat a little bit before. I'm just going to be honest with everyone when I said, Joseph, you know what I've known of you for so long, but I don't know you really deeply. And I was trying to kind of learn some interesting things about Joseph as we were talking and he just kept being super. And he's like, "I don't know, this is interesting. I don't know if anybody cares." But one of the things that he shared with me is that he comes from an ultra-Orthodox community. And I said, well, I don't know anything about that. And I told him, I know the very boundaries and the very edges and just the fascinatingness of how little I know about your life and your community and stuff like that could fill multiple podcasts.

Matt Stauffer:
So I was like, how can I winnow it down to one question, one final question. And you mentioned that you play clarinet and I would love to hear what the sort of music that you're playing is. And so my question for you is if somebody was interested in hearing the type of music that is played in your community, where would they go about even getting a chance to hear that?

Joseph Silber:
So ultra-Orthodox Jewish music sometimes called Hasidic music. I'll maybe give you the spelling for that later and you can put it in the show notes.

Matt Stauffer:
I know this one.

Joseph Silber:
Oh, you do?

Matt Stauffer:
H-A-S-I-D-I-C, right?

Joseph Silber:
Yes. There you go.

Matt Stauffer:
All right. And is ultra-Orthodox the same as Hasidic or not?

Joseph Silber:
No, but most Hasidic people are ultra-Orthodox.

Matt Stauffer:
Got it. Okay, cool.

Joseph Silber:
So what's called Hasidic music. You can search for that on YouTube. You can search for that on iTunes and Spotify. You can find that any way you want. I can give you some names of some popular artists.

Matt Stauffer:
I was just going to say, if you give me some names of the popular artists afterwards, I'll put them all in the show notes for everybody. Okay.

Joseph Silber:
Okay. Sure. That sounds exciting.

Matt Stauffer:
And also one thing I could ask you from right now, for the people who don't want to go to the show notes later. Could you tell me, maybe not your favorite song ever, but if you just wanted to introduce someone into one of your favorites or one of the most well-known, or one of the most representative songs from this kind of Hasidic music, what would it be?

Joseph Silber:
That's a tough one. I have so many good ones, but the audience is not familiar with any of them. If I have to pick one, it's like a really old one. It's called in Hasidic pronunciation, it's called [Hebrew language]. And that is Psalm, I don't know which number Psalm it is, but it was popularized by George Bush after 9/11. He said, "For though I walk in the valley of death." Maybe you know which number that is. You can look it up.

Matt Stauffer:
I'll look it up. Yeah.

Joseph Silber:
But it's sung in its original Hebrew words and it's a beautiful song. Maybe I'll play it on my clarinet. I'll give it to you to play here.

Matt Stauffer:
Oh goodness. If he sends me this clarinet audio y'all I am going to put it, it's going to be after the outro music, I'm actually going to put it right in the podcast. And I'm going to wait to release this until you see it. But if not, if you don't have it by then I will link it in the show notes. So yeah, definitely check the show notes for this one, for sure.

Joseph Silber:
Yeah, but I have to warn you. I'm an amateur. I'm no pro. I just play it for myself-

Matt Stauffer:
You said that but the fact that you're willing to play for us and [inaudible 01:19:44] is a huge risk. So I'm going to take it.

Joseph Silber:
That's myself, no one else.

Matt Stauffer:
Psalm 23:4 is where it is. So, and I definitely am I'm terrible with numbers and all that kind of stuff. So

Joseph Silber:
Yeah. So whatever your belief system is, everybody can just connect with that song now because I don't want to get too much into COVID now, but it's a challenging time. And we all feel the way we feel and we're looking for a path out and we'll get there.

Matt Stauffer:
Yeah. And we're looking for community and support and wisdom and there's a lot that can be brought from that when we look at what people have been talking about for hundreds and thousands of years.

Joseph Silber:
I guess you're looking at it, maybe you can read two passages of it.

Matt Stauffer:
Yeah, man, let's do that. So Psalm 23:4 actually, I mean the main one that people primarily are going to use and I know that the New Living is often more readable. Is there a living here, New Living. So this is the least, it's actually a little bit less popularized this way. But I think New Living is often more readable. "Even when I walk through the darkest valley, I will not be afraid for you are close beside me, your rod and your staff protect me and comfort me. And you may have heard though I walk through the valley of death, I will fear no evil for you are with me, your rod and your staff they comfort me." That's the King James. No King James is, "Yea though. I walk through the valley of shadow of death."

Matt Stauffer:
But regardless the truth is there. And I think that what I really appreciate you saying, there is just the idea that regardless of whether or not the rod and the staff whatever all or anything like that, or people don't have a particular religious belief. I've been talking to my kids about religious beliefs recently and they just ask, "Well, what's true?" And one of the things that's been really helpful for us is saying, "Well daddy might think this, or mommy might think this, or some of your friends might think this."

Matt Stauffer:
And what we don't say is like, "Nobody knows or whatever because some people think they know." But what we say is here are some shared experiences. Here are some shared comforts that we have. Here are some shared hopes that we have or something like that. I think that's been really helpful for them not knowing. They want us to just tell us what the answers are about faith. And for my family, at least in particular, we say, here's what we've got, but here are the things we can hope in. And here's the things that we can find comfort in. And so I appreciate you kind of specifically sharing this one, because like you said, this is a tough time and you may not feel the same as other people who are listening to this podcast religiously or whatever, but you may still find comfort and I hope you find comfort. And I know that Joseph does, which is why he brought this up. So comfort and peace. So thank you. And I'm really excited to listen to this song too, because I'm hoping it also will bring me and other people comfort and peace, so.

Joseph Silber:
Okay. Yeah. Hope so. Thank you.

Matt Stauffer:
Man, I appreciate you. Okay. So how can people follow you? What kind of stuff are you up to? Is Twitter the best way to follow you? Or is there anything else?

Joseph Silber:
So I don't really have that much of an online presence besides the actual code.

Matt Stauffer:
Yeah. So GitHub/Joseph. What is it? Joseph_Silber?

Joseph Silber:
So on Twitter it's joseph_silber because that's the only one that was available. GitHub is actually just Joseph Silber.

Matt Stauffer:
Okay.

Joseph Silber:
But that's B as in bravo, not V as in Victor.

Matt Stauffer:
That's S-I-L-B as in bravo, E-R.

Joseph Silber:
Yes. So you can follow me on Twitter. You can read my blog post and I never mind my blog that I never update. I actually just had a huge-

Matt Stauffer:
I was going to say there's a recent one, so.

Joseph Silber:
Yeah, there's a recent one on Lazy Collections. You should check it out. I think it's a good one. I spent a lot of time perfecting it. We updated that frequently. So it's basically Twitter and my blog. Yeah.

Matt Stauffer:
Awesome. Well, I will make sure those are all linked to the show notes. I will make sure that all this stuff the music that you recommend, everything like that, we'll get that in the show notes as well. And of course, links to all the topics that we talked about will be in there. So Joseph, thank you so much, man. This was an incredible pleasure. I really enjoyed it. I really think that everyone learned including me from what you had to share. And of course we're all benefiting from some of the code you've written. So thank you for your service to us. Thank you for joining me here today. And I just really appreciate you.

Joseph Silber:
Thank you very much.

Matt Stauffer:
All right. See y'all next time.