Installing Socialite Packages 0:00New to Laravel is an optional package called Socialite that makes the process of handling third-party authentication incredibly simple. So what I mean by that is, if you want to add a Login with GitHub button to your website, well, we could use Socialite for that, and the same would be true for, say, Facebook or Twitter. It's pretty darn nice, so why don't we dig in and learn how to use it. The first step is to pull it in through Composer. Remember, this is an optional first-party package. So let's grab it. Laravel slash Socialite, and we'll grab anything 1.0.So let's grab it. Laravel slash Socialite, and we'll grab anything 1.0. And then while we're here, I know we're going to generate a migration, so I will pull in Ways slash Generators, but this isn't relevant to the lesson, so don't worry about this if you're not familiar with them. So we'll grab 3.0. And then finally, if we want to write some tests, we could pull in PHP spec, and I'll grab anything 2.0. Just keep in mind that if you're not familiar with these two packages, it's OK. The main thing we're focusing on in this lesson is Socialite. Registering GitHub OAuth App 0:55Just keep in mind that if you're not familiar with these two packages, it's OK. The main thing we're focusing on in this lesson is Socialite. So with that out of the way, let's do a Composer update to pull this in. Now, while this is downloading, we need to set up a new application with whatever third-party provider we're using. In this case, we'll stick with GitHub, but the basic process will be the same if you're using something like Facebook. So here I've logged in to GitHub. I will go to Settings, down to Applications, and register a new application called Layercast Demo.I will go to Settings, down to Applications, and register a new application called Layercast Demo. I will set the home page. And then finally, the callback URL. This one is important. Now the basic process is, if a user tries to log in with GitHub, we will redirect them to a special page on GitHub's server where they will be asked to give us permission to access some of their private information, such as their email address. So once they give authorization, GitHub will link them back to some page in our application, and that's what this URL will be. Configuring Services and Env 1:52So once they give authorization, GitHub will link them back to some page in our application, and that's what this URL will be. So we are working locally right now, so let's just send them to Login, and then click Register. Now take note of our client ID and the client secret. We need to store this information. So back in our project, I will go into Config, slash Services, and this is where Socialite's going to look. So in our case, we're using GitHub, and this is where we can store the client ID, as well as the client secret, and then also the redirect URL. Now because these are private keys, yes, if you want to, you could store them here, oras the client secret, and then also the redirect URL. Now because these are private keys, yes, if you want to, you could store them here, or if this file is included in your version control, you may not want to do that. Instead, do something like this. Create a new .env.php file. Now we can return an associative array, and each of these keys and their values will be translated into environment variables. So in our case, we want GitHub client ID, and I will paste that in, and then also we want GitHub client secret, and then I'll grab the other one as well, like so, and that'll do it.want GitHub client secret, and then I'll grab the other one as well, like so, and that'll do it. So now, back in services.php, I can simply do get.env, GitHub client ID, and then the same thing here, GitHub client secret. Finally, for the redirect URL, you need to make sure that this is the same as what you specified when creating your GitHub application. So in our case, we called it localhost 8000, slash login. And that's it. So at this point, I think we're ready to dig in. Why don't we set up a home page, and this will be sort of our test page. Building Login Route and Controller 3:35So at this point, I think we're ready to dig in. Why don't we set up a home page, and this will be sort of our test page. So here's what I'm going to do. I will say, if auth check, then let's send them a message, return, welcome back, and then grab their username, auth user username. Otherwise, I will return, and forgive me for not using a view here, hi guest, and then a login link. So link to login, which we will create, and we'll say login with GitHub. Okay, that should do the trick. So let's create that login route and send them to, how about auth controller at login.Okay, that should do the trick. So let's create that login route and send them to, how about auth controller at login. And while we're here, let's go ahead and generate that controller. So make controller, auth controller, and just a plain class is fine. Okay, let's take a look at that and get started. So we need our login method. And what is the first step? Well, when we're using OAuth2, the first step will be to redirect the user to, in this case, GitHub server, where we can request access to their profile information, as well as the email address that they have on file.GitHub server, where we can request access to their profile information, as well as the email address that they have on file. So how do we want to tackle this? Well, we'll take it in two steps. First, I'll show you the basic facade usage, and then later, we will extract some kind of class, maybe something like create user. Okay, but first things first. So you'll see that we have a new socialite facade. However, in order to use that, make sure that you go to app.php within your config directory. And first, register the socialite service provider.However, in order to use that, make sure that you go to app.php within your config directory. And first, register the socialite service provider. And if you want to take a look at that, here's the path, Laravel socialite, socialite service provider. And then also while we're here, let's pull in the generators that we installed as well. Okay, generators, generators, service provider. Next, if you do intend on using that socialite facade, you can register an alias for it here. And once again, if you don't know the path, let's just hunt it down. It's Laravel socialite facades socialite. And that'll do it.It's Laravel socialite facades socialite. And that'll do it. So now, back in our auth controller, we can reference this here. Now, the basic API is really simple. For example, let's say we want to socialite using GitHub. And now we have access to exactly two methods here. Let me show you. The interface is called provider interface. And we have a redirect method. And like I was saying, that will redirect you to GitHub server to request authorization.And we have a redirect method. And like I was saying, that will redirect you to GitHub server to request authorization. And then we also have a user method that will actually fetch that information using an access token that GitHub will send to us. So let's try this out. So we're on the home page, but already it's failing. And this is an easy one, it can't find link two, because don't forget in the latest version of Laravel, the form builder and the HTML builder have been removed. So if you still want to use them, that's no problem at all. Just make sure that you pull them in from your composer.json file.So if you still want to use them, that's no problem at all. Just make sure that you pull them in from your composer.json file. So illuminate slash HTML, and anything for the form builder. So illuminate slash HTML, and anything 4.0. And then we can do a composer update. All right, that's done. So let me boot up the server again. And then also don't forget to reference that service provider. So up here, illuminate HTML, HTML service provider. All right, that should do it.So up here, illuminate HTML, HTML service provider. All right, that should do it. And now those helpers should automatically be available as well. So if we switch back to the browser and refresh, there we go. So I will log in with GitHub, and if we did it correctly, that should redirect us back to GitHub server, where we can now authorize the application. Now notice when we accept it, this will give us a redirect loop right now, but that's an easy fix. The important thing to note is that it's directing to the login URI, and it's passing through this unique code.The important thing to note is that it's directing to the login URI, and it's passing through this unique code. Now the basic way this will work is we request authorization, GitHub will return a unique code, and then we will fetch that code and submit another request to GitHub server to request what we call an access token. And think of that as sort of like a substitute for a password. It's a unique token that we can use to request information about the user from GitHub's API. So with that out of the way, let's dive back in. Back in our auth controller, what could we do here? Well, if we want to use the same URI, then you could always do something like if inputBack in our auth controller, what could we do here? Well, if we want to use the same URI, then you could always do something like if input has code. Then in that case, well, we don't need authorization, we can go ahead and create the user or log them in. Otherwise, we will redirect them to GitHub. So that would work. But really, if you think about it, there's a number of things that we'll have to do. Not only do we have to redirect to get authorization, but we'd also need to send another request to get information about the user. Extracting AuthenticateUser Class 8:37Not only do we have to redirect to get authorization, but we'd also need to send another request to get information about the user. We might need to reference our own user repository, we will need to log the user into our application. So I don't want to put all of that stuff within my controller. Instead, why don't we default to a class that has a descriptive name, something like create user, or even authenticate user. Any of these would be fine. So let's dig in and see how we can do that. The first step is, and I'm just going to put it in my app directory here, authenticate user.The first step is, and I'm just going to put it in my app directory here, authenticate user. Now, I'm thinking that this will have some kind of execute method. So let's think about what kind of dependencies we might have here. What would this class require in order to do its job? Well, the first thing that comes to my mind is the socialite package. So let's pull that in. And notice that I'm actually referencing a contract here, the socialite factory class. So let's call that socialite. And then next, what might we need?So let's call that socialite. And then next, what might we need? Well, we also need to log the user in. So let's pull in the authenticator contract, we'll call that auth. And then finally, I said we might need a user repository. So why don't we create that class as well. And we'll call that users and then initialize all of these fields. Okay, and then before I forget, let's go ahead and create that repository. Why don't we just store it within repositories. And we called it user repository.Why don't we just store it within repositories. And we called it user repository. All right, we'll come back to that. So now if we come down here to our execute method, we need to determine if we should redirect to GitHub server. Or if we already have a code, we can forego that part. So maybe we could do this. Within auth controller, I could inject this authenticate user. And then we could say authenticate user and execute. Now I can pull in the request class.And then we could say authenticate user and execute. Now I can pull in the request class. And that will be illuminate HTTP request. And then just fetch the code. So request has code. Hopefully that makes sense. We want to authenticate a user. And we're passing in a Boolean to indicate if the current request has a code param in the query string. And if it does, it means we are returning from GitHub.the query string. And if it does, it means we are returning from GitHub. So let's go back. And then within the execute method, we can accept a has code param here. Now that makes it really easy. I can say if we don't have a code, then, well, what are we trying to do? Well, that means we need to get authorization first. So why don't we just name a method like that? Return this get authorization first. And I will generate that method.Return this get authorization first. And I will generate that method. Now using socialite, I can say this, socialite, and I could say with if I want, or I could also just do driver. With is just an alias for that. So using my GitHub driver, let's redirect. Otherwise, if we do have a code, then we can move on to fetching information about the user from GitHub's API. And once again, we can do that by saying, using the GitHub driver, let's fetch information about the user.And once again, we can do that by saying, using the GitHub driver, let's fetch information about the user. And behind the scenes, it's automatically going to grab the input from the request. So you don't need to worry about passing that in. So before we move ahead, I want to stop and just give you an example of how this works. So why don't we say user, and then die and dump that to show you the output. But before we do that, to show you the flow, when we hit the login page, all we are doing is returning authenticate user, execute, and then we pass in a Boolean indicating whether or not there's a code associated with the request. Now when a user hits this login route, there won't be a code.or not there's a code associated with the request. Now when a user hits this login route, there won't be a code. So if we take a look, that means we will get authorization first. However, once they do get information, we will redirect them back to that URI. However, this time we do have a code, which means we will fetch information about the user and then just dump it out on the page. All right, let's see that in action. I will login with GitHub, and whoops, it looks like we forgot to import this class. So let's import that really quickly, and then try again. Give it another try, login with GitHub, and there you go.So let's import that really quickly, and then try again. Give it another try, login with GitHub, and there you go. All the information we require, including my email address. So now, as you might expect, we just need to translate this into either a new user record or fetch an existing user using the information that we see here. So that means right here, maybe we could add a method on our user repository called find by username or create. And then we basically want to pass this in. So why don't we call this get GitHub user, something like that, create the method, and paste that in.So why don't we call this get GitHub user, something like that, create the method, and paste that in. And that looks good. So then at that point, we'll save that to a user, at which point we can just log them in. So let's say this, auth, login, our user, and we do want to remember them. And then finally, we need to redirect somewhere, but we'll come back to that. We will use a listener approach for that in just a few minutes. For now, let's go ahead and implement this method. Find by username or create, we'll call that user data, and then we can just use layercastFor now, let's go ahead and implement this method. Find by username or create, we'll call that user data, and then we can just use layercast user. And then right here, do something as simple as return user first or create, and then just pass in the associated details. For example, username will be user data nickname. Or by the way, we could also just pass in an array into the repository if you'd prefer. But we'll stick with this, and that will be user data email. And then finally, why don't we just grab the avatar? That's all we care about in this case.And then finally, why don't we just grab the avatar? That's all we care about in this case. User data, and we'll fetch the avatar. And that's all there is to it. So if we have a user in our system that matches these attributes, then we'll just return it. Otherwise, if we don't, then we will create the user. So with that in mind, we should create a migration. phpArtisan generate migration using my package here. Otherwise, use phpArtisan make migration. So I will say create users table, and the fields will be a username, which should beOtherwise, use phpArtisan make migration. So I will say create users table, and the fields will be a username, which should be unique, an email that should be unique, an avatar, and that can be optional. And then we also need a remember token. So let's go ahead and add that one on manually. So right here, all user tables require a remember token if we're going to use Eloquent. Now I've already specified that I want to use a SQLite database or an SQLite database. So that means I should be able to run phpArtisan migrate, and that'll do it. Next, before I move ahead, I want to go to my user model and set my fillable fields. And this will protect us against some mass assignment vulnerabilities.Next, before I move ahead, I want to go to my user model and set my fillable fields. And this will protect us against some mass assignment vulnerabilities. So username, email, and avatar, like so. So that means if we go back to authenticate user, we should be getting there. So let's see. So if we don't have a code, let's fetch authorization. Otherwise, if we do, then let's try to find a user in our system that matches the data that was returned from that request. And then ultimately, we will log them in. That being said, how do we deal with, for example, determining how to redirect the user?And then ultimately, we will log them in. That being said, how do we deal with, for example, determining how to redirect the user? And for that, I think for this lesson, we will use a listener approach. So essentially, we execute an action, and then we will pass a reference to the current object. And then within here, we will call this listener, or maybe we will create an interface for that. And that way, we can call methods on the listener. For example, if we were able to log the user in, then why don't we return listener, and how about user has logged in, and then we'll pass in the user object. That way, from our controller, we can create a nice little method here.how about user has logged in, and then we'll pass in the user object. That way, from our controller, we can create a nice little method here. User has logged in, which will accept the user, and we will just return redirect to the homepage. That's all we're doing here. Now, like I was saying, if you want to, you could even create an interface for this. For example, let's extract an interface here, and I'm going to call it authenticate user listener. And the namespace, we're just putting it in the app directory here. Now, all we care about will be the user has logged in method.And the namespace, we're just putting it in the app directory here. Now, all we care about will be the user has logged in method. And that'll do it. If we switch back, we're now implementing that listener, which means within our authenticate user class, we can now expect an instance or implementation of authenticate user listener. And if you're confused, basically what that affords us is the assurance that whatever listener is provided here will offer this method and whatever else we add to it. So let's go back. Let me add my doc blocks, and then we'll take a look over this. I think this looks pretty good.Let me add my doc blocks, and then we'll take a look over this. I think this looks pretty good. So a class for authenticating a user, and our execute method, we determine if we need to redirect. Otherwise, we find or create the user. We then log them in, and then we call a user has logged in method on the listener. And that will simply, if I go over here, redirect to the homepage. Even better, notice how the login method on our controller is pretty darn simple. It's exactly one line, and that's really what we want. We don't want to be doing tons of logic within our controllers.It's exactly one line, and that's really what we want. We don't want to be doing tons of logic within our controllers. So why don't we try this out? We want to log into a site with GitHub. We will give authorization, and there you go. We've now created a user and logged them in pretty easily. Now if I go to log in again, notice it will still work. Now if I go to log in again, it will still work. Or even if you want, you could add a filter there. And mostly that does it. Sketching Phpspec Tests 18:51Or even if you want, you could add a filter there. And mostly that does it. Now I was hoping to be able to get to some tests, but this just went a little too high on time. So with that in mind, let me give you a basic idea of what some tests might look like. I will run phpspec describe layercast slash authenticate user. And now if we take a look at that spec. Now like I said, because we're too high on time, I will just paste in a couple examples to get you started. So first we have to define how to construct the authenticate user class.to get you started. So first we have to define how to construct the authenticate user class. So we mock our user repository, the Socialite factory contract, and the authenticator contract. And then we just describe what it does. It requests authorization for a user. So we say when we call Socialite driver, that's going to return a mocked version of the provider interface. And then if we call execute on the class and then specify that we have no code, well, that means a redirect method on the provider class should be called. And that's it.means a redirect method on the provider class should be called. And that's it. Pretty simple. Next, it creates a user if authorization is granted. So we mock out whatever we need. And then ultimately, this is what puts things into motion. So if we call execute and we have a code, well, in that case, we should call a method on our repository. We should then send a message to the authenticator to log in the user. And then finally, we should mock the authenticate user listener interface and then specify thatWe should then send a message to the authenticator to log in the user. And then finally, we should mock the authenticate user listener interface and then specify that a message called user has logged in should be triggered. And then finally, here at the bottom, because we don't actually want to hit any of these APIs, we can stub it out. So to give you an example of how that works, notice right here when we request our GitHub driver, well, we're not really interested in how that works. It already has tests. So I'm just going to create a little stub there so that when we request information about it, we can fetch it right here.So I'm just going to create a little stub there so that when we request information about it, we can fetch it right here. Anyhow, if we try to run this, phpspec run, it's under test. So if we, for example, were to change anything, for example, you accidentally removed that or something, well, it wouldn't matter because your test would immediately alert you that you're doing something wrong and the user has not been logged in. All right. So I hope you enjoyed this lesson. If you have any questions at all, just chime away in the comments below.If you have any questions at all, just chime away in the comments below.