
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
Complete source code available till this point of lesson is available at
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:02 I actually took some time to prepare this flow diagram for you, where I can show you in detail exactly how authentication works.
00:00:10 I'll explain it once right now, then we'll build out the exact steps that will allow this to happen, and then we'll revisit it so hopefully you fully understand
00:00:19 how everything works, not only in theory, but also in code.
00:00:23 So first of all, we have an anonymous user right here that clicks sign in with GitHub.
00:00:30 That's a button on a Next.js page.
00:00:33 Then we initiate an auth request over to NextAuth, which then redirects the user to GitHubAuth.
00:00:40 The GitHubAuth then presents a prompt for authorization to the user.
00:00:46 User presses yes and authorizes the app.
00:00:49 After that, GitHub redirects over to NextAuth with the auth code.
00:00:54 NextAuth then exchanges the code for the access token.
00:00:58 And finally, GitHub returns the access token back to NextAuth, which then creates a session.
00:01:05 We set the session into a cookie, and finally, we are redirected to the authenticated page, which is the homepage in most cases,
00:01:12 with the full session, including the user data, such as name, username, and email.
00:01:17 Now, let me show you how we can do this in code.
00:01:20 First, I'll install a new ShadCN component by running mpx-shadcn-add-latest-add-toast.
00:01:30 The toast is a little notification that shows up and gives the user some kind of a notification.
00:01:35 Next, we want to create a new file called constants.
00:01:39 So let's do it right here in the root of our folder and call it constants.
00:01:45 Within constants, create a new file called routes.ts.
00:01:50 This is another amazing enterprise level tactic to use in all of your future apps.
00:01:56 Basically, you can define a new object called routes that allows you to simplify your routing names.
00:02:04 Like if you go to home, you can simply define home right here as the forward slash route.
00:02:09 And we can do the same thing for sign in, which is going to point to forward slash sign in.
00:02:14 And we can do the same thing with sign up, which points to sign up.
00:02:17 After that, we can export default those routes.
00:02:21 Now, you might be asking yourself, like, why are we doing this?
00:02:25 Why are we declaring a separate object and then basically recalling this variable, which is just a string, nothing else.
00:02:32 We could have retyped this string.
00:02:34 Well, there are many benefits of doing this.
00:02:36 First one is reusability.
00:02:38 You can point users to the sign-in route from many different places, many different buttons, and many different pages.
00:02:45 Now, what happens if the URL for the sign-in route changes?
00:02:49 You would have to go ahead and change that route in every single place.
00:02:53 But if you have a centralized place where that route is stored, you can just go here and exchange it here, and immediately this variable change would be
00:03:02 reflected everywhere where it's used.
00:03:04 but not even that is the primary reason why I like to use it.
00:03:07 The primary reason is that if you are redirecting somewhere, let's say that you have a redirect, and then you type, for example,
00:03:15 forward slash sign in something, it is very easy to make a typo right here.
00:03:22 And if you make a typo, it sometimes is very hard to notice it but with the variables approach you can say something like redirect to sign in and if you
00:03:34 mistype it immediately you're going to get an error message saying that sign in is not defined but routes.signin actually is.
00:03:44 So this is one quick way to make your code less error prone and more reusable.
00:03:49 Again, it'll start making more sense once we use it within the code.
00:03:52 Now we can go to the components folder, specifically the social auth form, and we can implement the sign in for GitHub.
00:03:59 Let's do it by declaring a new const handleSignIn function, which is an async function that accepts the provider we want to sign in with,
00:04:11 which can either be GitHub or it can be Google.
00:04:15 So we're already letting TypeScript know that.
00:04:17 Then we can open up a try and catch block.
00:04:21 In the catch, we can console log the error as well as show a toast.
00:04:27 So let me show you how we can trigger a toast.
00:04:29 The only thing you need to do is say toast coming from hooks use toast.
00:04:36 To it, you can pass the title, such as sign in failed, and you can pass in a description as well, which is going to be equal to,
00:04:47 if an error is an instance of error, in that case, we can render the error.message because message exists on the error type.
00:04:56 Else, we can show a predefined string of an error occurred during sign-in.
00:05:04 And finally, we can also give it one more variable or one more prop of variant is equal to error.
00:05:12 Or rather, I think Shadzian does destructive.
00:05:15 Yes, this definitely is a destructive toast if we cannot sign in successfully.
00:05:19 So we want to show it to the user.
00:05:21 Why don't we go ahead and throw a new error right here and say, not implemented.
00:05:26 And let's give it a shot.
00:05:29 Of course, we need to call the handle sign in somewhere.
00:05:32 So we can call it right here on our button click.
00:05:35 We can say on click is equal to a callback function where we call handle sign in.
00:05:43 And in this case, we pass GitHub as the provider.
00:05:47 We can also duplicate this onClick and pass it to the second button, but this time we'll say that the Google is the provider we're trying to sign in with.
00:05:56 You'll notice that we immediately get an error, and that's because we're using some onClick functionality, which basically makes this a client component.
00:06:04 So now is a good time to add a use client directive at the top to fix this issue.
00:06:09 You'll also notice that we have a hydration error.
00:06:12 I'll look into fixing that soon.
00:06:14 But for the time being, let's try to see this toast in action by heading over to our general layout.
00:06:20 And then right below the body, we can place a toaster, self-closing toaster component.
00:06:26 As simple as that.
00:06:28 Now, if you click login with GitHub, you can see sign-in failed, not implemented.
00:06:33 Good, at least we know that is working.
00:06:35 And I think it makes more sense placing it within the body right here.
00:06:39 There we go, this is good.
00:06:40 And we can go back to SocialAuth, and we can focus on implementing the try block, meaning how are we actually going to do the functionality.
00:06:48 It is pretty simple.
00:06:50 You await sign in function, which is coming from nextauth forward slash react.
00:06:57 To it, you provide the provider and then you have an options object where you have a callback URL, which is going to go to routes.
00:07:05 And make sure to import that routes from constants routes.
00:07:10 And then we can have a redirect set to false.
00:07:14 See, if you misspell home here, it points to an issue.
00:07:17 But if we were using regular strings and if you misspell it, no issue there, right?
00:07:21 So it's always better to use constants, which are declared in a separate file.
00:07:25 Great.
00:07:26 And I think that putting the toaster in the body actually fixed the hydration error.
00:07:30 As you can see, it's no longer appearing for me.
00:07:33 But if you're seeing a hydration error, and if you try to fix all of the mistakes in your code, then it's possible that it is due to some browser extensions
00:07:43 modifying the HTML.
00:07:44 So in that case, maybe you can reload if it's still there, keep testing it, and try disabling your extensions one by one.
00:07:51 With that said, now that we have implemented the handleSignIn function, let me actually teach you about the two ways in which we can sign in using GitHub
00:07:59 or any other provider, or even through credentials in Next.js.
00:08:03 One is within client components, like this one we're within right now.
00:08:07 You can notice that in client components, nextAuthReact automatically exposes the sign-in function, which you can then use to authenticate right here.
00:08:17 Basically, on click, you await and sign in.
00:08:21 Another way would be handling it not within a client component, rather on the server.
00:08:28 In that case, you would await a different function.
00:08:31 Sign in, but not from Next React, rather from add forward slash auth.
00:08:37 And then you would use a React 19 form component that would look something like this.
00:08:43 Let me actually paste it here below this button.
00:08:47 that allows you to pass a form action where you can specifically declare only this block of code server-side.
00:08:54 This would allow you to render the entire form on the server without your browser ever needing to access JavaScript code.
00:09:02 Again, that has some of the benefits, but in today's day and age, I still prefer handling forms on the client-side.
00:09:09 as it allows us for more detailed and more granular error handling.
00:09:13 So you can let your users know what they typed in wrongly, how they can fix it, and how they can submit the form.
00:09:19 Now with that in mind, let's actually try to access the session that'll be generated once our user signs in.
00:09:26 To do that, we need to wrap our whole application with a session provider in app layout.
00:09:32 So right here, I'll go over the body and I'll wrap it in a session provider coming from next auth react.
00:09:41 And I'll wrap it right here below the body.
00:09:43 Then we have to declare the actual session, which we can do right here by saying const session is equal to a wait.
00:09:53 auth, which we call as a function coming from add forward slash auth.
00:09:58 Since we're using a wait, we have to make this function async.
00:10:01 So this is going to be an async function root layout.
00:10:05 And see how this is a bit complicated since it's using the expert default immediately here.
00:10:09 Let's actually turn this into a regular arrow function by saying const root layout.
00:10:14 is equal to an arrow function, which accepts children like this.
00:10:19 It is of a type children react node, which we can import right here from the top.
00:10:24 And then we end it here.
00:10:26 Yep.
00:10:27 That's much better.
00:10:28 And then we can run export default.
00:10:31 root layout right at the bottom.
00:10:34 Great.
00:10:35 And now it's easy to turn it into async.
00:10:39 Great.
00:10:39 So now that we have this session, we can pass it into the session provider by saying session is equal to session, and it will automatically feed all of
00:10:48 the other pages with the session of the currently logged in user.
00:10:51 So what can we do?
00:10:53 Well, let's try to log in.
00:10:55 I'll click login with GitHub, and I'll be redirected to authorize the dev flow.
00:11:01 Going back to our illustration, we're now at this point where I clicked sign in with GitHub, I initiated an auth request,
00:11:08 and then it redirected me to GitHub OAuth.
00:11:11 Then GitHub OAuth prompted me to authorize, which I will gladly do right now.
00:11:16 So I'll click authorize, and we got redirected to the homepage.
00:11:20 As you can see, many steps here happened in between.
00:11:23 Then we authorize the app.
00:11:25 GitHub reaches out to NextAuth with the auth code.
00:11:28 NextAuth reaches back to GitHub with the exchange code for the access token.
00:11:32 And then GitHub OAuth finally returns the access token, creates a session, sets the session cookie, and then redirects us back to the homepage.
00:11:41 I hope that makes sense.
00:11:42 So the main question is, do we have access to the currently logged in user session back in the homepage?
00:11:49 Let's head over to the homepage and let me turn this into a regular return function by wrapping it in a function block with a return statement.
00:11:59 And right here, I'll say const session is equal to await auth coming from add forward slash auth.
00:12:08 And I'll try to console.log.session.
00:12:12 If we do that, we of course have to turn our home into an async function.
00:12:16 And since we don't have the use client directive at the top, I would be expecting for that console log right here in my terminal on the server side.
00:12:25 And would you look at that?
00:12:27 user with a name of adrianjsmastery with an email and the avatar image, as well as the expiration timestamp for that session are all returned to us within
00:12:37 a simple auth session.
00:12:39 So now that we're on the homepage, we can now add the functionality to logout.
00:12:44 And in this case, I'll actually be using server-side to show you how we can handle forms completely on the server-side so we can tackle both approaches.
00:12:54 I'll create a new form, and within it, I'll render a button, coming from Components UI button, with a type of Submit, and it'll say Log Out.
00:13:06 To this form, I'll pass a class name of padding X of 10, and padding top of 100 pixels, so we can just see it below the knob bar.
00:13:15 Also, to this form, I'll pass an action, which is going to be equal to an async callback function right here, inside of which we can say use server,
00:13:25 which will ensure that the code below strictly gets used on the server.
00:13:29 And then we can write await.
00:13:31 Sign out.
00:13:33 Coming not from NextAuthReact, but from add forward slash auth, because we're using it on the server side.
00:13:40 And it also allows you to pass a redirect to property.
00:13:44 And let's redirect it to routes coming from constants dot sign underscore in.
00:13:51 Perfect.
00:13:52 So what do you say that we go ahead and give it a shot?
00:13:55 I will console log the session just one more time to see if it works once we get back to this page.
00:14:02 I'll click log out.
00:14:04 It logged us out.
00:14:05 I'll click login with GitHub again.
00:14:08 It's not going to ask us to reauthorize because it knows who we are.
00:14:12 And would you look at that?
00:14:13 We get back the information right here for the second time.
00:14:17 Wonderful.
00:14:18 You just implemented authentication using OAuth with GitHub.
00:14:22 In the next lesson, we can do a very similar thing, but this time with Google.