تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Guards in Laravel Auth0:00

Let's take a look at some different forms of authentication in Laravel 5.2. So let's go to config/auth.php, and let's take a look. Well, it looks like we're setting a default guard equal to web. And if we scroll down a bit more, yeah, it looks like out of the box, Laravel ships with two different guards. The web guard, which is the same session-based authentication that you've been using all this time. It's just now associated with that keyword name of web. But also we can see there's another one called API, and in this case, it uses an entirely different driver called token. So it seems if we break this down, Laravel offers session-based authentication.

and in this case it uses an entirely different driver called token. So it seems if we break this down, Laravel offers session-based authentication and now token-based authentication right out of the box. But further, if you want to create your own guard that requires some kind of special form of authentication, then you could create your own custom guard right here and then reference it anywhere in your code base. But anyhow, let's see. So driver token and then driver session. Well, if we take a look at this session guard,

Auth Manager Internals0:58

So driver token and then driver session. Well, if we take a look at this session guard, once again, this is the typical guard that you've been using all this time. So for example, if I go to our user method, this is the method that gets called when you run auth()->user(). And in fact, just in case you're curious, why don't we review this? I always find it helps me. So we're going to go to Laravel's auth Manager class. And let's see. I'm going to take you to a guard method. Mostly just come along for the ride. You don't have to memorize all of this.

And let's see. I'm going to take you to a guard method. Mostly just come along for the ride. You don't have to memorize all of this. So anyways, this is the method that will be called behind the scenes. Once again, if you were to say auth guard, and then you specify your desired choice. web is the default, but if you want to override that with API, you could do that. And then something like this. Or if you just say auth check, behind the scenes it's still going to call the guard method. And as we can see right here, we get the default driver,

behind the scenes it's still going to call the guard method. And as we can see right here, we get the default driver, which means if you don't specify anything and you just do auth check, like we did right here, well, we're going to use the web guard. However, if we override that and say guard API, well then of course we're going to use the API guard. Okay. So now what happens? Well, we check to see if we have cached it, so to speak, but otherwise we resolve it. So let's take a look at that. Next, we get the configuration.

but otherwise we resolve it. So let's take a look at that. Next, we get the configuration. If we go to that, yeah, notice that we're going right into that auth.php configuration file. And we're finding the guard specific to whatever you requested. That would be web by default, or API if you override it. So take a look. auth, guards, and let's say web. Okay. We take a look at that. We come down and we say auth, guards, and then web is the default. So we're fetching this bit of configuration. Now Laravel is just going to use those keys to build up the proper driver and the provider.

So we're fetching this bit of configuration. Now Laravel is just going to use those keys to build up the proper driver and the provider. So if we were to go back to our auth manager and we check out that resolve method once again, yeah, we get that configuration array. And then we say call the appropriate method that builds up the driver. So this will call essentially this createSessionDriver. And that's because we set session right here. So we're just building up the session driver. Now if we take a look at that session driver,

So we're just building up the session driver. Now if we take a look at that session driver, yeah, we figure out our user provider. That is the class that's responsible for fetching the User. Generally, you won't have to worry about that too much. We can use what Laravel offers out of the box. But anyways, we build up our session guard. And then we apply some setters and yada, yada. We don't need to go much deeper than that. All right. So what we can see here is right now when I say driver session,

We don't need to go much deeper than that. All right. So what we can see here is right now when I say driver session, behind the scenes that's giving us a session guard. And then down here that would give us a token guard. So that means if we were to hunt that down, token guard, well now for the situations where you say auth guard API and then check user or guest, all of those methods, this class is now responsible for that. So let's see how it fetches a user. Okay. Well, if we're using a token-based authentication,

How Token Guard Works4:04

So let's see how it fetches a User. Okay. Well, if we're using a token-based authentication, yeah, we're not going to have a login page. We're not going to have anything stored in the session. This will be stateless. So instead we will require the caller to pass in an API token like this. So let's go over this. Right here we're just checking to see if it's cast. You can ignore that. But yeah, right here, getToken for the request.

You can ignore that. But yeah, right here, get token for the request. So what this is going to do is basically say request input and then whatever the proper key is. And by default that will be api_token. So this class is going to look for that key in the request. Now if it didn't find one, it's going to try in a couple of different ways. But let's just assume we're passing through an API token key. Finally, we return that. And if I switch back, as long as we have a token,

Finally, we return that. And if I switch back, as long as we have a token, we're now going to tell our UserProvider to find a User that has that specific token. So let's take a look at that one. Now in this case you can see at the bottom I have a database UserProvider. Actually, if we go back to our configuration, we should be using the Eloquent specific driver. So let's go to our next one. Yeah, here we go.

So let's go to our next one. Yeah, here we go. Okay, so this will be Eloquent User provider. This is the method that will track down the User. And all we do is basically new up a User and then we say for each of those credentials, like this, apiKey equals some random hash, we're going to build up the query and then return the first result. Now I know I'm digging into the code and that can be a little confusing, but I do think it helps.

Now I know I'm digging into the code and that can be a little confusing, but I do think it helps. Anyways, this ultimately breaks down to something like user where the API key, and on that note it looks like we'll need to add an API key column to our users table is equal to some kind of hash and then return the first result. And that's it. That's all there is to it. We're not storing anything in the session for the next page load. No, this is all stateless. Okay, so yeah, I know that was a little confusing.

Designing an API Route6:22

let's see how we can use this in real life. Okay, so imagine that, imagine you're building something like Lyricast and you want to have an iPhone app to go with it. Okay, well, your application would want to offer an API, right? And that way, really, any application you build can query that API and in some cases, it'll need to return private information about the user. So how do you get around that? How does the application have permission to get information about that user? Well, typically, the user will generate an API key with your application.

So maybe we could do something like this. Let's prefix any routes with API, or some people like to version it. That would be okay. And next, we'll nest any routes that we might have. All right, so the simplest option would be a User wants to fetch information about their account, right? So we could do this. Route::get /user/{user}, and I'm just going to reference a closure here.

Route, get user /user, and I'm just going to reference a Closure here. You might want to reference like a namespaced controller, something like that. That would be fine. That's probably what I would do. Anyways, this will accept our user, and we will return it. Notice that in this case, we're using route model binding to make this really easy.

Adding API Token Column7:54

Notice that in this case, we're using route model binding to make this really easy. Anyways, I'd like to try this out and see how it works, but we don't have a database yet. We don't even have a User. So I'm going to go to my database.php configuration file, and if I scroll down, we'll use SQLite, and then I will touch a database file here. Great. Now, at this point, we could php artisan migrate,

Great. Now, at this point, we could php artisan migrate, and that would be fine, but remember, we talked about adding a unique token to the User's account. So I'm going to do this. I'm going to go to my create_users_table migration, and we'll add that right here. Table, and let's do something like this. string api_token.

Table, and let's do something like this. String API token. That should be about 60 characters, but also, of course, we should make sure that this is a unique API token. Okay, so I'm going to save that, and now I will run php artisan migrate:refresh. So roll everything back and rerun them. Okay, so why don't we build up a test User? So I'm going to go into my database/factories

Okay, so why don't we build up a test User? So I'm going to go into my database/factories/UserFactory.php class. Here is the blueprint, so to speak, for a User. Let's add the API token, and that can be str_random(60) characters. That way, we could do something like this: php artisan tinker factory(User::class)->create(); And there we go. So we have a new User named Sally,

And there we go. So we have a new User named Sally, and notice a unique API token. So this is something she could generate from her account, and she could then provide that to any third-party app that would request that information. Notice it's not their password, so they can't sign in with that information, but it does give them access privileges to query any sort of data that we need to protect.

but it does give them access privileges to query any sort of data that we need to protect. Okay, so before we test this out, let's review what we have so far. We've created a route group, and we've specified that if we try to track down a User by their ID, all we want to do is return a JSON representation of that User. So that means right now, well, I could just boot up a server.

So that means right now, well, I could just boot up a server and then access API v1 users and then their ID, and we can access that information. And yeah, notice I'm not signed in, but I can still access this information. Okay, so we want to add a layer of authentication on top of it, and in reality, you would want a second layer to ensure that the requester has permission to view this specific account.

Applying auth:api Middleware10:16

to ensure that the requester has permission to view this specific account. I'm not going to go that far. We've covered all of that already in the GATE lessons. So for now, let's just assume if you provide the proper authentication, you can view any of this information. All right, so what we could do is something like this. I could say middleware auth, like we've reviewed in the past.

I could say middleware auth, like we've reviewed in the past. And now what that's going to do is ensure that you are authenticated before you can access it. Now, in this case, it's failing only because I don't have a login page, but it is doing its job. So great, that works for the web, but what about when you're making API calls?

So great, that works for the web, but what about when you're making API calls? Well, it's a little bit different, right? For example, let's try this out here. I have a tool called HTTPie that you can pull in. You can pull that in through Homebrew. We've covered that on the site. Very useful. It just gives us an easy way to make a PUT request or a PATCH request,

It just gives us an easy way to make a PUT request or a PATCH request, rather than having to learn all of those confusing options. Anyways, let's make a GET request, or GET is the default, so I can leave that off entirely. Anyways, let's make a GET request to our server, api/v1/users/1. And now if I do it like this,

so it responded accordingly. And by the way, if you're curious about how that works, it's stored within your Kernel class. So if we go into app/Http/Kernel.php, and I scroll to the bottom, notice that this auth middleware, well, that corresponds to the authenticate middleware here.

notice that this auth middleware, well, that corresponds to the authenticate middleware here. Now if we take a look at that, yeah, here we go. So if we have an AJAX request, or we want JSON, then as long as the user is a guest and they're not signed in, yeah, we're just going to return a 401. Otherwise, it's a web app,

yeah, we're just going to return a 401. Otherwise, it's a web app, in which case we can redirect them to a login page. But now what I want you to take a note of is, well, right here, you can pass through the guard as a parameter. And then notice once again, like we reviewed at the beginning of the video, that will be referenced here.

like we reviewed at the beginning of the video, that will be referenced here. So it looks like if I want to use API-specific authentication or a token-based authentication, well, I could say off and then pass through a parameter of API. Now that will be assigned to the guard variable and we'll pass it through. So in effect, we're doing this.

and we'll pass it through. So in effect, we're doing this. Let's try that one out now. I'm going to undo. I'm going to go back to my routes file. And now I'll say I want API-specific authentication. And remember, now we're not going to use the session guard anymore. We're going to use the token guard that looks for an API key in the request.

We're going to use the token guard that looks for an API key in the request and then it tries to hunt down the User where the API key is equal to what we passed through the query. Okay, so now we're going to run it, but we're still unauthorized, right? Okay, let's do it again, but this time I'm going to pass through an API key. Now I can do this like this,

Foo equals bar and bar equals foo. It's just a convenience. Anyways, let's do this. API key equals something that's not right. If we run that, we're still unauthorized. But now let's use the proper key. And real quick, I will boot up php artisan tinker to fetch our key. App User first. There it is.

App User first. There it is. So that's something the user once again would generate and hold on to or pass to the third-party app. Okay, so I'm going to run it again, but this time paste in the key. And it still fails. What did we do wrong? Oh, I'm sorry. I set it to API key. API token is what we want.

Oh, I'm sorry. I set it to API key. API token is what we want. That's the query that Laravel will look for. And I got to prove it to you. So if we go to token guard, let's look for API. Yeah. So that will be the input key that we're looking for. API token. Okay, so this time if we run it, there we go. We passed through a unique token for the user.

Okay, so this time if we run it, there we go. We passed through a unique token for the User that matched up. So that means, yeah, you have permission. You can access this route. And remember, once again, we're just making sure that they have the token. And if so, we're assuming they can access any User. In reality, that may not be the case, in which case you would want to add the Gate facade.

It's going to fail, run authorize, and exit. Now, real quick before we finish up, what if, I'm going to go back to my routes file, what if maybe we set up a home route here, and that's just going to return information about whoever was authenticated. So basically this, I'm going to get rid of that entirely. But instead, we're going to say something like auth user. All right, well, how does that work? Let me show you.

All right, well, how does that work? Let me show you. Let's save it. Let's make a request using the proper API key. But now I'm going to remove this section entirely. This is only as an example. So right now, the token was correct, but authUser is equal to null. And that's because, remember, this is still going to use a default of web for the guard.

And that's because, remember, this is still going to use a default of web for the guard. So that ultimately translates to this. If we want to use API, then we have to be explicit for these routes. Okay, so now if we run it, there you go. That's an important note to make. And of course, if you're building an app where you want the API guard to be the default, then just go to your auth configuration file,

where you want the API guard to be the default, then just go to your auth configuration file, and if we scroll to the top, set your default guard to API. And now you wouldn't have to do that. You could come back here and just say auth user. Okay, run it again, and now that's the default, so we once again fetch that information. Okay, and I think that'll do it for this lesson. So you got a quick peek behind the scenes to figure out how we build up these drivers

So you got a quick peek behind the scenes to figure out how we build up these drivers and what exactly we're doing to verify the token. As a quick recap, what you need to do is ensure that you apply the proper middleware. So auth will use our session-based middleware, but auth:api, well, that passes through an argument to the middleware that says, no, we actually want to use the API guard here. Next, you want to make sure that on your users table

that says, no, we actually want to use the API guard here. Next, you want to make sure that on your users table that you add an API token column, and you want to make sure generally pretty common that it will be 60 characters and it should be unique. And finally, assuming that you do have the web guard by default, any time you want to access information about the user, you would want to override the default guard to be API. But now you can still use the same interface, so check or guest or user.

But now you can still use the same interface, so check guest or User. All right, that's it. Let me know if you have any questions.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟