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

Intro and project setup0:00

The first question in this how-to series comes from Bill Trenton on Facebook, and he asks, how can I authenticate users with GitHub? Luckily, Bill, if you're using Laravel, it really couldn't be easier, and that's because we have access to Laravel Socialite. So let me show you every step of the process in this video. I'm going to go to my code directory and create a new project. We'll call this Auth with GitHub. So let's cd in there. And real quick, if I switch back to Chrome, I'm on the GitHub page for Socialite, and you'll see that it does not come pre-installed with Laravel.

Install and configure Socialite0:29

And real quick, if I switch back to Chrome, I'm on the GitHub page for Socialite, and you'll see that it does not come pre-installed with Laravel. We have to pull that in. So take a look. We require it. We update our providers array in our config/app.php file. We add an alias, and then we update our services.php file. Okay, let's do all of those. So composer require. Next, I'll open this in Sublime, switch to our config/app.php file,

So composer require. Next, I'll open this in Sublime, switch to our config/app.php file, and like most packages with a Laravel service provider, you will need to do this. So you scroll down to your provider section, and we're just going to paste in the path to the Socialite service provider. So I'll put that right here. Next, it wants us to add a global alias. So basically, when you use the Socialite class, it's going to point to this full namespaced version. And we can do that right down here.

it's going to point to this full namespaced version. And we can do that right down here. So now what's the next step? You'll need to update your config/services.php file, and you're going to paste in the client ID and the client secret for GitHub, or you can use Socialite for Facebook or Twitter or lots of stuff. We're just focused on GitHub because it's pretty common, especially for developer-focused sites. Okay, so we're going to go to config, services, and this is where you're going to put generally any third-party keys and stuff like that,

Register GitHub OAuth app2:14

Here, we'll just go home. You can see I'm signed in as myself, and I'm going to go to settings, OAuth applications, and here's everything I've granted access to. Let's add a new one. So developer applications, register a new one. I'll call this tutorial, and the homepage URL will just be, it can be a local host URL or a .dev domain name. So for example, in this case, I'm using Laravel Valet, which means I should have a domain called authwithgithub.dev. So if we run that, yeah, it works great.

which means I should have a domain called authwithgithub.dev. So if we run that, yeah, it works great. That's a nice thing about Laravel Valet. Definitely research it if you haven't. Okay, so the homepage URL will be that. Remember, this is for development only. I would then change this later for production. Next, we have authorization callback URL. So basically, the way this works is you're going to click on a login link on your website, and Laravel or Socialite is going to redirect you to GitHub,

So basically, the way this works is you're going to click on a login link on your website, and Laravel or Socialite is going to redirect you to GitHub, and there is where you will grant authorization. So once you do that, GitHub will then redirect the user back to a callback URL with a unique token that you can then use to fetch all of the data associated with the GitHub user. Okay, so this specifies where in fact are we redirecting the user, and it can be anything you want. So what a lot of people do is something like auth/{provider}/callback.

I'm just going to grab that once again and paste that in here. So especially for small stuff, this is really fine, especially if no one would ever view your Git repo. But generally, as a good rule of thumb, I like to store this stuff within configuration files, if only for the bonus that you can have one ID and secret for local development and another one for production. So with that in mind, we're going to go to our .env file, and then down here, I'll set a few new ones. So let me center this for you.

Add routes and controller5:12

So you know what? I think we're just about all set to go. The only remaining thing is to create the routes, and then use Socialite to redirect the user to GitHub. So if I go back to Chrome, let's take a look. GitHub Laravel Socialite. And we should be able to see some routes to add. Okay, so basic usage. You can see an AuthController. You redirect to the provider.

You can see an AuthController. You redirect to the provider. When we say provider, in this context, don't think of a Laravel service provider. Think of an authentication provider, like Twitter or Facebook or GitHub or Google. Anyways, so yeah, this is something we can use right here. So let's grab these guys, go to our routes file. That's not right. Go to our routes file.

That's not right. Go to our routes file. And I'm just going to spit this out right here. Okay, so when we make a GET request to auth/GitHub, we're going to load an AuthController and a method redirectToProvider. Next, this one's important. Notice the structure here. That matches up exactly with what we used here. So if I come back and just paste that in,

That matches up exactly with what we used here. So if I come back and just paste that in, yeah, notice it's the exact same endpoint. Okay, so now once GitHub sends the user to this URL, we're going to load AuthController at handleProviderCallback. And you can name these methods whatever you want. Okay, so if we go into app/Http/Controllers/Auth, you'll see we already have an AuthController. But now in this case, it has a lot of boilerplate.

you'll see we already have an AuthController. But now in this case, it has a lot of boilerplate specifically for a traditional login system. But if we're only interested in GitHub, for example, I believe the guys over at Laravel.io, they just do authentication with GitHub and nothing else. That's very cool. So that means, yeah, we can basically get rid of all of this junk, you know? So let's do this.

all of this junk, you know? So let's do this. Let's just empty that out. And I'm going to need a User, but that's about it. Okay, so which routes do we need? redirectToProvider. And then another one for handleProviderCallback. Okay, let's get started using Socialite. So use Socialite at the top. And to redirect, yeah, you don't have to figure out

So use Socialite at the top. And to redirect, yeah, you don't have to figure out what the endpoint is or any of that stuff. Socialite has drivers that'll do this for you. So we're going to use the GitHub driver, and I only need to call redirect. So cool. So let's try it out. We'll go to auth with github.dev. Okay, so we're going to visit auth/GitHub,

and it's going to send through a unique token, a GitHub token, which is just like any other third-party token. Whether you're using Stripe or something else, it's a accessToken that you can then use to request information about the user. And once again, that's something Socialite 's going to do for you just behind the scenes. It'll be seamless. You call a single method, user, and then Laravel will use Guzzle to make an API request.

You call a single method, user, and then Laravel will use Guzzle to make an API request. It'll pass through that unique token and fetch the user. That's pretty cool. Okay, so I'm going to authorize the application, and notice we did trigger this URL, and take a look at this unique code. That's the access token that we'll use. Okay, so in this case, we haven't set anything up here, but we are on the right track.

Handle callback and fetch user8:45

Okay, so in this case, we haven't set anything up here, but we are on the right track. So back to Sublime, we're triggering this method. Let me give you some more space to see here. What do we do next? Okay, well, we've redirected the User. They've granted permission. We've redirected to the callback URL. So we now fetch the GitHub user, and we can do that by saying Socialite::driver('github'),

So we now fetch the GitHub user, and we can do that by saying Socialite driver GitHub, and then give me the user. Okay, so that's going to give you the GitHub-specific user, and that'll have everything from their avatar to their GitHub ID to even information about their repositories. And in fact, let me just show you this because I think it'll make it a little bit more clear. So when I say Socialite driver, let's just take a look.

because I think it'll make it a little bit more clear. So when I say Socialite driver, let's just take a look. Come along for the ride for just a minute. If we go to createGitHubDriver, this method is being triggered. So when I say Socialite driver, it's going to call the createGitHubDriver, and that'll return to us a GitHub provider. Now, there's no user method on here, like we're trying to call right here.

Now, there's no user method on here, like we're trying to call right here. That's stored on the parent abstract provider. So let's go in there. Now, if we go to user, there it is. Okay, so don't get too confused by this. This is all I really want you to see. Get user by token. So if we go there, yeah, here you go. So we get that token from the callback URL,

So if we go there, yeah, here you go. So we get that token from the callback URL, and then we use that to make an API request. We fetch Guzzle, perform the request, then get the response, decode it, and save it to the User object. And that's it. So I hope that makes a little more sense as to what's going on behind the scenes. Anyways, now that we have the GitHub user,

and now we have this information. The GitHub ID, our nickname, an email, an avatar, that's a picture of me. And then finally, if you need extra information about the user's GitHub account, you can use that. Okay, so that's kind of step one of this process. Redirecting to GitHub, granting authorization, redirecting back to Laravel, and then fetching the user. So now step two is adding this to your database.

Persist user and sign in11:09

and then fetching the User. So now step two is adding this to your database if it's not already there, and then signing in the User. Let's do that now. Why don't we do something like this? $user equals, and basically, you have to think of it like this. In some situations, we will have created the User, and in other situations, it'll be the first time signing up. So maybe I could say something like,

and in other situations, it'll be the first time signing up. So maybe I could say something like, findOrCreateGitHubUser. Yeah, maybe something like that. findOrCreateGitHubUser. So this needs to accept the GitHub user, which means I should pass this into the method. But in this case, I'm just going to inline it, the information. Okay, so now, yeah, this should be pretty easy. I should be able to say $user,

Okay, so now, yeah, this should be pretty easy. I should be able to say User, give me the first record in the database, or build up a new instance. Now, we want to be careful because we don't want to use something like this. So we don't want to say GitHub User. And if I go back to Chrome, yeah, we can get the email field there. So we can't do this because it may be possible.

that will not change, and it's something we can also store in our own database. Okay, so we could say first or new GitHub ID. And don't worry, we haven't created that table just yet. We'll do that in a bit. And we'll compare that against GitHub user ID. Okay, so yeah, that's either going to give us an existing User, or it'll create a new instance of User. So we could say if User exists in the database, then we're done, we found the User.

So we could say if User exists in the database, then we're done, we found the User. So in that case, let's just return User and be done with it. Otherwise, we need to build up the User's record, save it to the database, and then return. Okay, so we could then say User fill, and let's just pre-populate all the information. So let's do this. Let's go to create_users_table. And this is the User's migration.

Let's go to create users table. And this is the user's migration that comes with every Laravel install. So we give the name, the email. Password is irrelevant. We're using GitHub in this case. However, we do want to store that GitHub ID. So let's do that. table integer. And well, one option is you could have multiple providers,

Table integer. And well, one option is you could have multiple providers, and that gets a little bit more complex. But you could do something like this. In our case, though, we're only interested in GitHub. So we'll do that. Next, we know this needs to be unique, right? Every GitHub user will have one unique ID. So let's set that. Okay, next, I personally prefer username,

So let's set that. Okay, next, I personally prefer username, but that doesn't matter. We accept the email address. And then why don't we also fetch the avatar? That could be useful, don't you think? So let's do table string avatar. And yeah, I think that should be good. All right, so let's set up our database. Let's go to .env.

All right, so let's set up our database. Let's go to .env. I often use sqlite and then just use a database in memory. So let's say touch database/database.sqlite, and then run php artisan migrate. And that'll build up the users table and the password_resets, which is irrelevant. We don't even need that in this case. Okay, cool. So now that we have the User,

Okay, cool. So now that we have the User, yeah, we just pre-populate it. username will be, and then we just grab it from this information. So GitHub user, and let's grab nickname. Now, if you do have a system where the username needs to be unique, then of course you would update your migration. But we'll just make email the unique item here.

then of course you would update your Migration. But we'll just make email the unique item here. So email will be GitHub user email. Next, we want the avatar. So GitHub. So yeah, you can see here, we're just really mapping the GitHub information into our own User record. Finally, I do want that GitHub ID, and that will be GitHub user ID.

Finally, I do want that GitHub ID, and that will be GitHub user ID. And actually, you know what? We don't even need this because we instantiated it here. So let's get rid of that. We've filled the User record, and I'm just going to call save. Finally, I can return that User. And just be careful,

Finally, I can return that user. And just be careful, you can't do this, right? Because save would return a Boolean. So I do want to return the user object itself. All right, so does that make sense? We have our callback URL where we fetch the GitHub user. And then we're just saying, find me an existing User record.

And then we're just saying, find me an existing User record using the GitHub ID as our indicator or as our key. And if you found one, just give it back to me. Otherwise, you're new to our system. So I'm going to throw you into a new row in my users table. And I will use your GitHub information.

in my users table. And I will use your GitHub information for the username and email and avatar. So now, check it out. We have our User. I should be able to sign you in and then redirect you back to the homepage. So return redirect to the homepage. Okay, why don't we try this out? So back to Chrome,

Okay, why don't we try this out? So back to Chrome, we're going to hit that URL one more time. And actually, real quick, before we do this, let's go to php artisan tinker and then fetch all users from the database. None. Okay, so we run it. It redirects us back.

Okay, so we run it. It redirects us back. And integrity constraint. Oh, crap. Sorry about that. Here's the problem. Let's go back to the User model. We added a couple columns to our users table, like GitHub ID. Let's go to it.

like GitHub ID. Let's go to it. Yeah, we added GitHub ID and avatar. However, those weren't included in our fillable fields. So they get stripped out. So that's why it's failing. It became null, but it's telling us, you didn't tell us this field could be null.

but the path we take is a little different this time. So this time we find the User. They do exist in the database. So we return them and we never actually create the record. We just fetch the User and log them in. So why don't we test a couple of things out just for fun. So let's add to start a logout URL. And I'm just going to inline this to be quick. Auth::logout(), and then redirect to the homepage.

And I'm just going to inline this to be quick. Auth, logout, and then redirect to the homepage. Next, let's add one more for something like a dashboard. Something that you have to be signed in to see. So I'm going to add a middleware here. And I'm doing this on purpose because we're going to need to tweak the middleware just a bit. So we will return. You are authorized to see this page. Okay, cool.

So it links us to GitHub. Once again, we've already authorized that portion. So you don't have to do it again. It'll just redirect you appropriately. And now, once again, we're signed in. So now, yeah, we could go to, let's go to that welcome page. Down here, we'll say, I don't know, if auth check, then we'll say you are signed in as user username. Otherwise, you are not signed in. So end if, yeah.

So it fetches the User from the database. It does auth login, and it redirects us to the homepage. And that's it. So you're authenticating with GitHub. And really, it just isn't that hard at all.

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