- [Instructor] The last thing we are missing now
is this post complete route.
So let's look into server, routes, auth and GitHub.
And let's scroll down here,
and here we have the get complete route.
And further down, let's now implement this post route here.
And it turns out that this route is very similar
to the one we have for the registration.
So what I'm doing now is I open registration JS,
and I will now use this post register route
and just copy it over.
Of course, we have to change a few things,
but it gives us a good starting point.
So the first thing I'm doing is
I change post register to complete.
So this is where we end up
when the user provides username and email,
so it's valid to do validation here,
just not for the password,
because the password is, of course, not provided,
because it's a single sign on flow.
But what we need to bring in
is now this validation middleware, and that's easy.
So we scroll up and under the user service,
I'll now add const validation equals require,
and we have to go two levels up.
Yes, there are the middlewares
and there we have validation.
All right, so with that,
we can scroll back to the post route
and do our changes here.
So first of all,
the validation here,
starting in line 72, can stay as it is.
Then, we check for existing email and existing username.
That's also still valid, so that's still the same,
so we can leave everything here the same.
And here, down there, starting in line 100,
we render auth registration,
which is not where we want to end up now.
We want to render auth complete, of course,
because that's the complete route.
And then I want to render the form again,
where the user adds the username and password.
And also show the errors that occurred
when we end up here.
So if we don't run into an error,
we end up down here,
and now we have to change,
create user into create social user.
And as you know,
we pass in the username, the email,
and then we want to pass in this temporary OAuth profile.
And let's copy that.
We have it in the session.
So it's the request session temp OAuth profile,
because it contains the provider, GitHub,
and also the profile ID.
So you can now replace the password
with just this object that is stored in the session.
And then we say here,
your account was created and linked with GitHub,
so that we really know that we are in the GitHub flow now.
And let's see if we have to do something else.
No, that looks all good.
So now we should be good.
Right, now we are ready to test it out.
So I'm heading into the browser.
The first thing I'm doing is I'm also opening this account
that I have on GitHub for lcorla
and go back into settings,
and when I scroll down,
there is this applications link in the menu bar.
And there I had to authorize OAuth apps,
because there, you see,
this is the OAuth app that we authenticated
for the user in the flow before.
And I want to revoke that now again,
to really test all scenarios that we have now
with authentication.
So I choose revoke all
and I have to type in my username
to confirm that,
and now this is revoked, so we end up
in this authorization flow also
on the page to authorize this OAuth app for this given user.
So let's try that out.
So I'm heading into registration.
I click on sign up using GitHub,
and you see here,
I'm really ending up in this authorization flow again.
And now I click cancel to test the scenario
when the user does not want to authorize us,
and let's see what happens then.
And you see, yeah, we end up in the log in form again.
So that's okay, but if you remember that,
if we look into the code and up here,
this is the get complete route.
We actually would want to show an error here.
So we would want to show log in via GitHub has failed.
But for some reason,
now our messages do not work.
And I was struggling
with finding the reason for that before.
So I'm now showing you how I found out what's wrong here.
So for that, I'm now heading
into the browser again.
Now I'm opening Chrome developer tools and the network tab.
Let's try this flow again.
So I click on log in via GitHub.
Then, I cancel.
So now I'm ending up here again, very nicely.
You also see the whole flow of redirects that we have here.
So here you see, for instance,
we are on a redirect that contains the callback
and the error with access denied.
And when I click on this, you also see,
I can also disable this button.
So there is this checkbox
show filtered out request cookies,
and if I look at that,
you see that request cookies have been filtered directly
by the Chrome browser.
And when I hover over this same site strict,
you see that this cookie was blocked,
because we have same site strict as cookie option.
And this means, technically,
that Chrome filters a cookie
that comes in through a redirect from GitHub.
So from a third party and not from the same site,
and this is a problem because then, suddenly,
we create, basically, a new session on the server,
which is obviously a problem,
And so that's also the reason why
we suddenly cannot write the messages into the session.
So we have to change something here.
And this is rather easy,
while the theory behind this is rather complex,
because it's about standards and cookies.
But for us now, let's just fix this
by heading into app JS
And there, if we scroll down,
you see that there is the same site strict,
and I will now change this to lax.
So I'm having to relax these security constraints
a little bit, otherwise,
the session will be gone on this redirect.
And now I can try this again.
So I will now try to log in via GitHub.
Then I cancel.
And you see now I also get this error message,
because the session is preserved,
and this is technically what we really want to have.
Now, let's try this again.
So I click again on log in via GitHub,
but now I see authorize.
And I come back.
This is now the get routes to complete.
And there I will now first try lcorla,
lcorla@explorecalifornia.com
And let's click on create account.
And you see, we get this error message
that the email address or the username exists already.
Also exactly as intended.
See already, I'm really trying all the variations here.
So now let's try lcorla2,
still the same email address.
And you see, I get the same error still.
So now let's use this email address as well, lcorla2.
And now let's click on create account.
And now I see that my account was created
and linked to GitHub.
And now I still have to log in via GitHub.
And what I also have to do is,
to create the valid user,
is I have to verify the email address,
and I do this as we did before,
by just clicking on this verify user button.
Now the user is verified.
And now, I can hit log in and log in via GitHub.
and I'm lcorla2.
So now, I don't have to enter anything.
Behind the scenes though,
we really made the whole round trip here.
So again, we called into GitHub.
So the whole authentication flow was running
now behind the scenes still.
And then we got the profile with the profile ID,
and we were able to pull up the user
and lock in the user then.
So now let's try something else.
For that, I head to the user list.
And I have added one more feature to the user list.
You see that there is this red GitHub icon.
With that you can unlink the GitHub profile from this user.
It's just deleting this profile information
from the database.
So if I click on that, this is canceled.
Now, the lcorla user is no longer associated
with the user on GitHub.
This is good because now I want to link the lcorla,
so the real lcorla user, with the GitHub profile,
because sometimes you have an existing user
and you now want to link this user
to an existing social profile.
Because, in the future, they want to use social login,
and we can do that easily.
And technically, the flow for that is completely identical
with the authentication flow.
So you can basically click on any GitHub button
that I have here in the app,
because they all will go to auth GitHub,
and then start this flow.
So let's log out lcorla.
And while we are here, let's delete this lcorla user,
so to avoid confusion.
Now, let's log in with this user.
So now, I'm authenticated regularly,
as we were authenticated before.
And now, I'm heading to my account,
and there I have this connect account with GitHub button.
Again, you see in the browser,
on the bottom left,
this points to auth GitHub.
That's exactly the same flow.
It's just now, as you know, that in our route,
and let's look at that maybe again,
so in GitHub JS,
if we look at this get complete route,
you see that we look into the request,
if there is an authenticated user,
and if so, we just assign this profile to the user
by saving the profile information to it,
so, with that,
we can just click on connect account with GitHub
and you see now,
my GitHub profile was successfully linked again.
Now, when I log out lcorla and I go to log in,
I can now log in via GitHub.
And you see, now I'm lcorla again.
So now the whole GitHub authentication flow works
end-to-end.
And if you look into the database,
so in models, user model,
again, you see that we are agnostic to
which OAuth provider we use.
So this could be as well,
Facebook or Google or something else.
So with this structure, you can really authenticate
against any OAuth provider that is out there.
So all you have to do
is basically install the respective passport strategy,
configure it, and then also add the respective copic routes,
and you're good to go.
The database would be ready for it.
And with that, we have a working application
that supports various kinds of authentication.
Of course, we can improve a few things.
For instance, it does not make sense
to show registration or log in
for a user that is already logged in,
but this is something you just have to fix
in the template.
I just left it this way to make the handling
in the Playground app, and during development,
a little bit simpler.
But if you really understood everything we did now,
within this course,
you can really say that you have authentication
with Node JS, pretty much down.