Next-Auth Login Authentication Tutorial with Next.js App Directory

Dave Gray
1 Jul 202340:26

Summary

TLDRIn this tutorial, Dave introduces viewers to adding authentication to a JavaScript application using Next Auth. He highlights the ease of integration with Next.js, showcasing support for JSON Web Tokens and OAuth, including GitHub login. Dave demonstrates setting up Next Auth with the new Next.js app router, creating API routes, and customizing options for providers. He also discusses the use of Cody AI for code analysis and test generation, emphasizing its benefits for ensuring code reliability. The video concludes with examples of protecting pages and utilizing client components with Next Auth, encouraging further exploration of its customizable features.

Takeaways

  • πŸ˜€ The tutorial demonstrates how to add authentication to a JS app using NextAuth and Next.js.
  • πŸ”’ It introduces Kodium AI, a tool that generates tests to ensure code reliability and correctness, supporting JavaScript, TypeScript, and Python.
  • πŸ“š The video provides a step-by-step guide on setting up NextAuth with JWT and OAuth for GitHub login, emphasizing ease of use and customization.
  • 🌐 It mentions the support for serverless environments and the ability to use NextAuth without a database.
  • πŸ“ The script covers the creation of API routes and the use of the new app router in Next.js version 13.2 and above.
  • πŸ› οΈ The tutorial explains how to set up environment variables for NextAuth, including a secret for encryption.
  • πŸ”‘ The process of configuring OAuth with GitHub is detailed, including generating client IDs and secrets.
  • πŸ“± The script discusses different methods of protecting pages in a Next.js application, such as using server components and middleware.
  • πŸ–ΌοΈ It highlights the ability to display user data, such as images from GitHub, after OAuth login.
  • πŸ”„ The importance of using Next.js configuration to handle images from external sources is mentioned.
  • πŸ” The video concludes with an invitation for viewers to request more tutorials on advanced authentication topics like role-based authorization.

Q & A

  • What is the main topic of the video?

    -The main topic of the video is adding authentication to a JavaScript app using NextAuth and Next.js.

  • What is the sponsor for this video?

    -The sponsor for this video is Kodium AI, a tool that analyzes code and generates tests to catch bugs.

  • What does NextAuth support for authentication?

    -NextAuth supports JSON Web Tokens (JWT) and database sessions for authentication.

  • What is the default session handling strategy used by NextAuth?

    -The default session handling strategy used by NextAuth is encrypted JWTs, referred to as JWEs, stored inside a session cookie.

  • How does NextAuth handle OAuth authentication?

    -NextAuth handles OAuth authentication by allowing users to set up providers like GitHub, Twitter, Google, and Facebook, and configuring them with their respective client IDs and secrets.

  • What is the purpose of the 'credentials' provider in NextAuth?

    -The 'credentials' provider in NextAuth allows users to authenticate using a username and password combination.

  • How does the video demonstrate setting up GitHub as an OAuth provider?

    -The video demonstrates setting up GitHub as an OAuth provider by creating a new OAuth app in the GitHub account, obtaining the client ID and secret, and configuring them in the NextAuth options.

  • What is the role of the '.env.local' file in the NextAuth setup?

    -The '.env.local' file is used to store environment variables such as the NextAuth secret and provider secrets, which are essential for the authentication process but should not be shared publicly.

  • How does NextAuth apply authentication to the entire Next.js site?

    -NextAuth applies authentication to the entire Next.js site by using middleware that checks for user authentication on every page request.

  • What is the difference between server components and client components in Next.js?

    -Server components in Next.js are rendered on the server and can access server-side data, while client components are rendered on the client side and are typically used for interactivity. Server components are usually used as the parent, and client components are imported where needed.

  • How does the video handle user session data in client components?

    -The video creates a React context called 'auth provider' that wraps client components, allowing them to access session data from NextAuth.

  • What additional configuration is needed in Next.js to display images from external sources like GitHub?

    -To display images from external sources, the video mentions configuring 'next.config.js' with remote patterns to allow images from specific origins.

Outlines

00:00

πŸŽ“ Introduction to NextAuth for JS Apps

Dave introduces the tutorial on integrating NextAuth for authentication in a Next.js application. He mentions resources, a Discord server for discussion, and highlights Kodium AI as a sponsor, which generates tests for code review. The video covers setting up NextAuth with JWT and OAuth for GitHub login, using Next.js 13.4.7, and installing NextAuth with npm.

05:01

πŸ›  Setting Up NextAuth with Route Handlers

The tutorial explains how to set up NextAuth using the new route handlers in Next.js 13.2 and above. It details creating the necessary API routes and directories, and initializing the NextAuth configuration. The video also discusses NextAuth's support for JSON Web Tokens, database sessions, and its serverless compatibility.

10:01

πŸ”‘ Configuring OAuth and JWT in NextAuth

Dave walks through configuring OAuth for GitHub and setting up JSON Web Tokens in NextAuth. He explains creating a .env.local file for environment variables, including the NextAuth secret, and obtaining GitHub's client ID and secret. The process of setting up providers in the options object is also covered.

15:02

πŸ“ Implementing Credentials Provider and GitHub OAuth

The video demonstrates how to implement the credentials provider for username and password authentication and set up GitHub as an OAuth provider. It includes creating an authorized function for the credentials provider and using environment variables for storing sensitive information like GitHub's client ID and secret.

20:02

πŸ”„ Applying NextAuth for Site-Wide Protection

Dave shows how to apply NextAuth for protecting entire site routes using middleware in Next.js. He explains creating a middleware file and using a matcher to apply authentication to specific routes. The video also reviews different ways of protecting pages, such as using server components and NextAuth's auto-generated sign-in pages.

25:03

🌐 Utilizing Client Components with NextAuth

The tutorial covers using client components with NextAuth, including creating an auth provider with React context to share session data. It explains the use of the 'use client' hook, session handling, and conditional rendering based on authentication status in client components.

30:04

πŸ–ΌοΈ Displaying User Data and Images from OAuth Providers

Dave discusses displaying user data, such as images from GitHub, after OAuth login. He shows how to modify the user card component to display the user's GitHub image and mentions the need to configure Next.js for remote images from OAuth providers.

35:05

πŸŽ‰ Conclusion and Future Tutorials

In conclusion, Dave expresses his satisfaction with NextAuth's ease of use and customization options. He invites viewers to request future tutorials on topics like role-based authorization and thanks the audience for their support, emphasizing the importance of making progress in learning.

Mindmap

Keywords

πŸ’‘NextAuth

NextAuth is an open-source authentication library for Next.js applications. It simplifies the process of adding authentication to your app by providing a range of providers and customizable settings. In the video, NextAuth is used to demonstrate how to add authentication to a Next.js app with JWT and OAuth, including GitHub as a provider.

πŸ’‘Authentication

Authentication is the process of verifying the identity of a user or device. It is a critical component of secure applications. The video's theme revolves around adding authentication to a JavaScript application using NextAuth, showcasing different methods such as JWT, database sessions, and OAuth.

πŸ’‘JSON Web Tokens (JWT)

JSON Web Tokens are a compact, URL-safe means of representing claims to be transferred between two parties. In the context of the video, JWT is used as a method for session management in NextAuth, allowing stateless authentication which is ideal for serverless architectures.

πŸ’‘OAuth

OAuth is an open standard for access delegation, commonly used as a way for Internet users to grant websites or applications access to their information on other websites without giving them the passwords. The video covers setting up OAuth for GitHub login as part of the NextAuth configuration.

πŸ’‘Serverless

Serverless computing is the execution of code in response to events at any location without the need to maintain traditional server infrastructure. The video mentions that NextAuth is designed for serverless Next.js applications, highlighting its compatibility with cloud functions like AWS Lambda.

πŸ’‘Environment Variables

Environment variables are a set of dynamic values, set outside the application, that can configure the application's runtime behavior. In the script, environment variables are used to store sensitive information like the 'NEXTAUTH_SECRET' for NextAuth, enhancing security by not hardcoding secrets into the source code.

πŸ’‘API Route

An API route is a specific path in a web application's API that is used to handle client requests and server responses. The video explains how to add an API route for authentication using NextAuth, which is crucial for handling authentication logic on the server-side.

πŸ’‘Middleware

Middleware in Next.js is a function that runs on every request and has the ability to modify the request and response objects. The video demonstrates using middleware with NextAuth to protect entire sites or specific routes by applying authentication checks globally.

πŸ’‘React Context

React Context provides a way to share values like authentication status between components without having to explicitly pass props through every level of the tree. The script describes creating an auth provider using React Context to make session data available to client components.

πŸ’‘Client-Side Rendering

Client-side rendering is a process where web pages are rendered by the client's browser rather than the server. The video discusses the behavior of client components in a Next.js app, which are rendered on the client-side and can access session data through the auth provider.

πŸ’‘Server-Side Rendering

Server-side rendering is the process of generating HTML on the server before the page is sent to the client. The script contrasts server-side rendering with client-side rendering, noting the difference in how session data is handled and displayed in server components versus client components.

πŸ’‘Progress over Perfection

The concept of 'Progress over Perfection' is a philosophy that encourages making continuous improvements rather than striving for unattainable perfection. The video concludes with this message, encouraging viewers to make small, incremental improvements in their coding journey.

Highlights

Introduction to integrating NextAuth for authentication in JS apps with detailed tutorial and resources.

Invitation to join Discord server for web development discussions and support.

Sponsorship by Kodin AI, a tool for code analysis and test generation to ensure code quality.

Kodin AI supports JavaScript, TypeScript, and Python, and can be integrated into VS Code and other IDEs.

Demonstration of Kodin AI's test generation feature for code review and reliability assurance.

Installation guide for Next.js project and the importance of selecting the correct version for tutorial alignment.

Explanation of NextAuth's support for JSON Web Tokens and database sessions, and its compatibility with serverless environments.

Guide on setting up NextAuth with the new Next.js app router for API route configuration.

Step-by-step instructions for creating API routes using Next.js 13.2 and above with route handlers.

How to set up a custom options object for NextAuth, including providers and other settings.

The use of environment variables for storing NextAuth secrets and the creation of a .env.local file.

Configuration of OAuth for GitHub login, including setting up a new OAuth app in GitHub settings.

How to retrieve and securely store GitHub client ID and secret in the .env.local file.

Setting up the credentials provider in NextAuth for username and password authentication.

Different methods of protecting pages in Next.js using NextAuth, including server and client components.

Middleware implementation in Next.js for applying NextAuth across the entire site or specific routes.

Discussion on the use of server components versus client components in Next.js for optimal performance.

How to create an auth provider using React context for client components that require session data.

Final thoughts on the ease of use and customization options of NextAuth for Next.js projects.

Transcripts

play00:01

[Music]

play00:04

hello and welcome I'm Dave today we're

play00:07

going to learn how easy it is to add

play00:09

authentication to your next JS app with

play00:12

next auth and I'll provide links to all

play00:14

resources in the description below I'll

play00:17

also provide a link for you to join my

play00:18

Discord server where you can discuss web

play00:20

development with other students and you

play00:22

can ask questions that I can answer and

play00:25

receive help from other viewers too I

play00:27

look forward to seeing you there I'm

play00:28

ready for a highly requested tutorial

play00:30

about next auth with the new next.js app

play00:33

router but first i'm happy to introduce

play00:35

kodium AI as the sponsor for this video

play00:38

codium AI analyzes your code and

play00:40

generates meaningful tests to catch bugs

play00:42

before you ship to production or even

play00:44

before you have a code review with your

play00:46

boss or Mentor with kodium AI you can

play00:49

easily and quickly create comprehensive

play00:51

test Suites that help ensure the

play00:53

reliability and correctness of your code

play00:55

and Cody may I currently supports

play00:57

JavaScript typescript and python in VSCO

play01:00

code and several other popular Ides

play01:02

let's look at how it works just click

play01:05

the generate test button above any

play01:07

function and codium AI will begin

play01:09

generating tests for your code review

play01:11

the test created and even add your own

play01:13

custom tests also check out the code

play01:16

analysis and code suggestions I love

play01:18

these features and when you're happy

play01:20

with the tests save the test Suite to a

play01:22

file I'm going to provide links to their

play01:24

vs code extension and main website below

play01:27

hey guys adding codium AI to your vs

play01:30

code is as easy as going to extensions

play01:32

searching for kodium AI and then

play01:35

installing it it's free add it to your

play01:37

vs code extensions today okay let's get

play01:40

started I've already created a new

play01:42

next.js project and I've said yes to all

play01:44

of the questions as the project was

play01:46

created now looking at the package Json

play01:49

if you're completing this tutorial in

play01:51

the future you should note that I'm

play01:54

using next version

play01:56

13.4.7 its current as of today and if

play02:00

you want next to behave the way it does

play02:02

here in the tutorial you may want to

play02:04

install this version but I'm just

play02:06

letting you know that you could try to

play02:08

use the latest as well so after that we

play02:11

need to go ahead and install next auth

play02:13

so let's open up a terminal window once

play02:15

again type npmi and then next Dash auth

play02:19

and we'll install the next auth package

play02:21

we're back at the next auth website and

play02:24

I'm looking at the introduction they

play02:26

really have great docs and you can

play02:28

explore these because next auth is very

play02:30

customizable we're going to go over some

play02:32

of the basic settings for a quick

play02:34

implementation today and that will get

play02:37

you started and of course I could cover

play02:38

other customizable settings in future

play02:41

tutorials as well so let's look at some

play02:43

of the introduction here on next auth

play02:45

and I want to highlight just a few

play02:47

things we've got support for Json web

play02:50

tokens and database sessions and this is

play02:53

designed for serverless next.js does run

play02:56

on serverless but it can also run

play02:58

anywhere so next auth can work with AWS

play03:01

Lambda Docker Heroku Etc It also says

play03:04

own your own data here and I just want

play03:06

to highlight that it says it can also be

play03:08

used without a database and that's what

play03:10

we're going to do today we're going to

play03:11

use the default settings for JWT but

play03:14

we're also going to set up oauth for a

play03:17

GitHub login now let's go to the getting

play03:19

started link over here in the left hand

play03:20

menu and on getting started we're going

play03:23

to scroll down just a little bit and we

play03:25

can already see the install for next

play03:27

auth and we've already done that then it

play03:29

says add an API route but notice a lot

play03:31

of the examples here in the docs at

play03:33

least currently as I'm making this video

play03:35

show the old version here with Pages

play03:37

slash API slash auth but then you need

play03:40

to read some of the documentation as

play03:42

well because it says if you're using

play03:44

next.js 13.2 or above it does support

play03:47

the new app router and you can

play03:49

initialize the configuration using the

play03:51

new route handlers by following our

play03:53

guide so let's just go ahead and click

play03:55

that guide and look at the setup here

play03:58

for a route Handler you can see this has

play04:00

a different different path now it's in

play04:02

the app directory as we're provided in

play04:04

next js13.2 and above then we create an

play04:08

API directory inside then an auth

play04:10

directory and then this catch-all route

play04:12

here inside of brackets with the three

play04:14

dots that says next auth and then route

play04:16

TS so let's go to visual studio code now

play04:19

and do that back in vs code we need to

play04:21

open up the source directory if you

play04:23

added the source directory to your

play04:25

project if not you just have the app

play04:27

directory on that level and that's where

play04:29

you need to create the next directory or

play04:32

folder if you will inside and it's

play04:33

called API and then inside of that one

play04:36

we need to create another directory and

play04:39

this is going to be called auth and then

play04:41

finally inside of auth we need to create

play04:43

that catch-all that has a bracket three

play04:46

dots and then next auth and another

play04:50

bracket now inside of this directory is

play04:53

where we create the route.ts file we'll

play04:56

start by importing next auth and that's

play05:00

going to come from next Dash auth after

play05:05

that we're we're going to import options

play05:07

here in just a moment but I won't do

play05:09

that yet let's define our Handler

play05:12

and we're going to set this equal to

play05:14

next auth and this is where next auth

play05:17

will receive the options so it's going

play05:19

to have a red squiggly until we pass in

play05:21

our options object but after this we

play05:23

just simply need to export and we'll say

play05:26

Handler as get comma and also Handler as

play05:31

host so our route.ts file is not too big

play05:36

and you will see some go ahead and

play05:38

Define their options object inside of

play05:40

this file but I prefer to create a

play05:43

separate file so let's go ahead and do

play05:45

that and we'll just call this

play05:47

options dot TS we're back in the next

play05:50

auth documentation we're under options

play05:53

now in the left hand menu and looking

play05:55

under options the main thing we need to

play05:57

provide inside of our options object is

play06:00

the providers themselves what we plan on

play06:02

using so this is where we will say a

play06:04

GitHub provider that we're going to use

play06:06

with oauth we're also going to have a

play06:08

credentials provider and we'll learn how

play06:10

to set that up but there are some other

play06:12

settings they cover on this page so let

play06:15

me scroll down just a little bit it

play06:17

talks about a secret here we're going to

play06:19

need to set a next auth underscore

play06:21

secret as an environment variable so

play06:24

we're going to create a DOT env.local

play06:27

file in our next JS project for that and

play06:29

then there's some other settings they

play06:31

cover as well oh and we're going to use

play06:33

this by the way to go ahead and create

play06:35

that random secret we can do that easily

play06:37

with this command in the terminal okay

play06:39

underneath that a few other settings

play06:41

that we can look at although we're just

play06:43

going to use the default today so we

play06:45

will not need to provide these but I

play06:46

just want to draw your attention to them

play06:48

you can set some settings for a session

play06:51

here and this is where I wanted to

play06:53

really highlight this because note the

play06:55

default is a JWT that's encrypted so

play06:59

it's referred to as a jwe so if you've

play07:02

watched any of my previous React auth

play07:05

videos in the past where we use JWT this

play07:07

is a little different strategy but I

play07:09

really like what they're doing and

play07:11

really rather than rolling your own

play07:13

which creating your own like we did in

play07:15

that react auth series is a great way to

play07:18

learn about auth but this has a little

play07:20

more full featuredness to it and I

play07:22

really like how it's set up so I

play07:24

recommend this strategy actually and you

play07:26

would use this encrypted jwe that's

play07:30

stored inside of a session cookie so

play07:33

that's how they're doing this by default

play07:35

and then you could use a database

play07:37

instead but that's not what we'll be

play07:39

doing we will just be using the JWT that

play07:42

is once again the default so just

play07:45

highlighting that okay let's scroll down

play07:47

to just a little bit more and then

play07:49

there's also a JWT setting once again we

play07:52

won't need to do any of this because

play07:53

we're using the default and we're not

play07:55

using a database and then they've got

play07:57

some other settings for the JWT but the

play07:59

other one I want to find is pages so

play08:02

notice this this pages is a property

play08:04

here inside of that options object and

play08:07

then it has its own object here you can

play08:09

set up custom pages but if not these

play08:13

will be created for you they'll just be

play08:16

found at a specific address that next

play08:19

auth provides so if you wanted to create

play08:21

a custom sign in page then you could

play08:24

have it at say just slash sign in

play08:26

instead of the default which might be

play08:29

auth sign in or auth sign out and so on

play08:33

ours because of this new router or route

play08:36

Handler set up inside of the API slash

play08:40

auth directory everything that's created

play08:42

by default will actually be inside of

play08:44

Slash API slash auth and then then we

play08:47

would have our sign in and sign out but

play08:49

next auth creates these for us and so

play08:52

just by using the defaults we can

play08:54

implement this next auth quickly okay

play08:57

let's go back to the code and set up our

play08:58

options object and our next auth secret

play09:01

as well let's start with import type and

play09:05

then we need next auth

play09:08

options and this is also going to come

play09:11

from next Dash auth after we've imported

play09:15

our type we will import our providers

play09:18

when we're ready for those but let's

play09:19

first just set up the object so I'll say

play09:21

export const

play09:24

options and we'll set this of course the

play09:27

type being our next auth options we'll

play09:29

set this to an object then that has a

play09:32

providers and this providers is an array

play09:35

so this is where we will put our

play09:37

providers that we decide to import and

play09:40

use in our application now after this

play09:42

this is where we would put for example

play09:45

the pages object that we looked at so if

play09:48

we had a specific sign in then we could

play09:51

give the path for that so you might want

play09:53

to move it to just sign in but then you

play09:55

would have to create your own sign in

play09:57

page and next auth we'll create one for

play10:00

you so we're not going to provide this

play10:02

here the same for the session you would

play10:04

set a session and then set the related

play10:06

properties for that session that we

play10:09

looked at inside of the documentation

play10:10

but now we're just going to focus on the

play10:13

providers but before we go back to the

play10:15

docs and look at each individual

play10:16

provider let's go ahead and open up a

play10:18

terminal so control in the back tick now

play10:21

inside of the terminal let's type that

play10:23

command that will will just generate

play10:25

that random secret for us so it's open

play10:27

SSL

play10:29

Rand and then Dash base 64 and then the

play10:34

number 32. we'll press enter and there

play10:37

is our random secret that we have so we

play10:39

can just highlight and copy this with

play10:42

Ctrl C and now we need to go ahead and

play10:45

create a DOT env.local file in our next

play10:48

project and we want this on the same

play10:50

level as the package Json file so now

play10:53

let's create this file and it's dot

play10:56

env.local by default this would be

play10:58

listed inside of your git ignore file

play11:01

you never want to send your environment

play11:03

variables to GitHub so these are secrets

play11:06

you keep them in your Dev environment in

play11:08

the dot enb.local and then when you

play11:10

deploy your application you set the

play11:12

environment variables in your host

play11:14

whether that's versl or somewhere else

play11:16

that you would deploy your next JS

play11:18

application so this is a next auth

play11:22

underscore

play11:23

secret and we'll set it equal to and

play11:26

just paste in that value with control V

play11:29

is what I use to paste and now we have

play11:31

in that random value you will have a

play11:34

different value here and of course I'll

play11:36

delete these secrets in the future and

play11:37

won't be using those online so no luck

play11:40

using mine just go ahead and generate

play11:42

your own you will not find this dot

play11:45

env.local file in the source code for

play11:47

this video because as I said you do not

play11:49

share this file in your GitHub back in

play11:52

the documentation we're under

play11:54

configuration providers and then

play11:56

credentials this is where we would sign

play11:58

in with a username and a password and

play12:01

this is showing us how to set up the

play12:03

credentials provider that we would need

play12:05

to import at the top here and it has

play12:07

some explanations but I'll of course

play12:09

walk you through this as we created in

play12:11

our project as well and then another

play12:14

type of provider is oauth now oauth can

play12:17

be GitHub Twitter Google Facebook any of

play12:20

these providers that provide an oauth

play12:22

sign-in and you've probably seen before

play12:24

where you can just click sign in with

play12:26

GitHub or sign in with Google and so on

play12:28

so that's what we'll be setting up now

play12:30

there is a full list of them further

play12:32

down in the menu here under providers

play12:35

and then you can scroll to get the

play12:36

details for each one that you want to

play12:39

set up here's GitHub and after we scroll

play12:42

down just a little bit you'll see

play12:43

there's a link and we need to configure

play12:45

this in our GitHub account so now you'll

play12:48

already need a GitHub account to do this

play12:50

and so if you don't have a GitHub

play12:52

account I'd go ahead and suggest going

play12:53

to github.com and getting that free

play12:56

account set up and then coming back and

play12:58

do this but most of us probably already

play13:00

have a GitHub account at this point so

play13:02

let's go ahead and click this link and

play13:04

it should open up directly to the page

play13:06

we need of course inside of your GitHub

play13:09

account this one is mine as you can see

play13:11

my little icon up here in the top right

play13:13

so now that we're at the GitHub apps

play13:15

page we want to click on oauth apps and

play13:18

we want to set one up you can see I

play13:20

previously set one up as I did some prep

play13:22

for this tutorial now I'm going to click

play13:24

new oauth app here in the top right I

play13:27

need to give this a name so I'm going to

play13:29

call this

play13:30

next auth Dash Tut for tutorial and then

play13:35

the home page URL is going to be HTTP

play13:38

colon slash slash localhost colon 3000

play13:42

so this is for our Dev environment when

play13:44

you would deploy your application you

play13:47

would need to come back into your GitHub

play13:48

settings for this oauth setting and

play13:51

change it to your deployed URL and then

play13:54

the other URL here at the bottom

play13:57

authorization callback URL starts the

play14:00

same but after that we're going to have

play14:03

a slash and say API slash auth slash

play14:07

callback slash GitHub and that would be

play14:11

the full callback URL this is basically

play14:14

saying where it's going to send you

play14:16

after you authenticate with GitHub where

play14:18

should it send you back in your

play14:19

application so now let's go ahead and

play14:21

click register application and we should

play14:24

be good to go now what we want to have

play14:27

here is a client ID and a client secret

play14:30

we haven't generated that yet let's

play14:32

first get the client ID copied I just

play14:35

put my client ID in a text file for now

play14:37

and you could do the same or paste it

play14:39

into a file in vs code whatever just so

play14:42

you make sure you have that or you could

play14:44

come back to this tab then generate a

play14:46

new client secret and you'll need to log

play14:49

in if you're not logged into your GitHub

play14:51

or actually I was logged in they just

play14:53

want you to confirm access so you'll

play14:55

need to log in again okay I logged in

play14:58

and now notice I have make sure to copy

play15:00

your new secret client now you won't be

play15:02

able to see it again so make sure to

play15:04

just click the copy little icon here and

play15:07

copy this and again save it somewhere

play15:09

and we're going to put it in our DOT

play15:11

env.local so if you just want to go

play15:13

straight to that file we can do that now

play15:16

too so make sure you get it here because

play15:18

when you come back it will no longer be

play15:20

available to see the full length of this

play15:23

secret you would just have to generate

play15:24

another one if you didn't save it back

play15:26

in our DOT env.localfile I'm going to

play15:29

call this

play15:31

GitHub Secret

play15:34

and after that I'm going to set it equal

play15:36

to the value that I copied out of GitHub

play15:38

for the secret I'm also going to have

play15:41

GitHub underscore ID and I need to get

play15:45

that ID value that I saved in a text

play15:48

file and then I'll paste it in here as

play15:50

well so now I've got my GitHub ID and

play15:53

GitHub secret saved in the dot env.local

play15:56

file and it's worth noting that even the

play15:58

GitHub client ID that you have here

play16:00

changes for each one of those that you

play16:03

generate for oauth so this isn't the

play16:05

same between those and of course I'll be

play16:07

deleting this as well now that we have

play16:09

our secrets in our DOT env.local file

play16:12

let's go back and complete our options

play16:14

with the providers that we need to

play16:16

insert so once again at the top of the

play16:18

file we need to import each provider so

play16:20

I'm going to

play16:21

import then say git hub

play16:26

provider and this is going to come from

play16:29

next Dash auth slash providers slash

play16:34

GitHub and then I'm also going to import

play16:38

the credentials

play16:40

provider

play16:42

which should come from next

play16:45

Dash auth slash providers slash

play16:49

credentials okay we've imported both

play16:51

providers we need now let's set those up

play16:54

so I'll go ahead and create some space

play16:56

here in the array and the first is the

play16:58

GitHub provider then we have a

play17:01

parenthesis and an object inside now

play17:04

we'll have a client ID and this refers

play17:07

to the value that we set up for the

play17:09

GitHub ID so we want to say

play17:11

process.env dot

play17:14

GitHub underscore ID now notice

play17:18

typescript still doesn't like this and

play17:19

we can Mouse over and says type string

play17:22

undefined is not assignable to type

play17:24

string so we can just use an assertion

play17:26

here at the end because we know we have

play17:28

a string in r dot env.local file so we

play17:31

can just say as string remember an

play17:33

assertion is essentially telling

play17:35

typescript that you know better then

play17:37

we've got client secret we'll set this

play17:40

to process.env dot GitHub underscore

play17:45

secret and we can then once again say as

play17:48

string and that's really all there is to

play17:50

setting up our GitHub provider so our

play17:53

oauth with GitHub is ready to go now

play17:56

let's go ahead and set up the

play17:57

credentials provider it takes just a

play17:59

little bit more work but this is

play18:01

something you're almost always going to

play18:03

want as far as having users be able to

play18:05

use a login name and a password so here

play18:09

we're going to have

play18:10

credentials provider and then we've got

play18:13

a parenthesis and an object once again

play18:16

where the name here will just say

play18:19

credentials after that we've got a

play18:22

credentials property

play18:24

and here this is going to be an object

play18:26

and then inside of this object we're

play18:28

going to have a username set up which is

play18:30

another object so here let's say

play18:33

label and we're going to have this as

play18:36

username and this will actually appear

play18:38

on the page so I want username colon

play18:41

then after that there's going to be a

play18:43

type and this is a text type and then

play18:47

we're going to have a placeholder so

play18:49

really we're kind of defining our HTML

play18:51

input here and the placeholder you could

play18:53

put pretty much anything you want to I'm

play18:55

going to say your

play18:57

Dash cool Dash username so this is just

play19:01

a placeholder for that text field then

play19:03

after that we're going to have another

play19:06

comma here so we've got the comma for

play19:09

the credentials then we've got that's

play19:12

actually for the username and then we've

play19:14

got the comma or the credentials and

play19:17

after that we need to have an async

play19:20

function here that is an authorized

play19:22

function and we pass in those

play19:24

credentials that are received now this

play19:28

is where you would actually want to get

play19:31

your data from a database if you had a

play19:33

user database and you typically would

play19:35

with credentials or some place you're

play19:37

getting the information from where

play19:39

you've set up these users already I'm

play19:41

just going to hard code in a user and

play19:44

I'm just going to copy and paste this

play19:45

part in because it's mostly just a

play19:47

comment here that I wanted to note

play19:49

inside of the code for this tutorial to

play19:52

remind you this is where you would

play19:54

retrieve your credentials from whatever

play19:56

user table or other source where you are

play19:59

storing your user information so here

play20:02

I'll hide the file tree with control B

play20:04

just so we can read all of this but I

play20:06

said this is where you need to retrieve

play20:07

your user data to verify credentials and

play20:10

then reference the docs at this page

play20:12

where you shows how to configure the

play20:15

providers because they do Show an

play20:16

example of retrieving some user data and

play20:19

then comparing it so how that would work

play20:22

I'm just hard coding this user here

play20:24

which is my name Dave and a simple

play20:26

password next auth but you would not

play20:29

want to do this this will run on the

play20:31

server but this is not probably what

play20:33

you'd want to recommend by hard coding

play20:35

users that's not too flexible certainly

play20:37

doesn't grow with your application

play20:39

compared to setting up something where

play20:40

you would retrieve users from and now we

play20:43

just need an if statement so let's say

play20:44

if and we'll have our credentials that

play20:47

the

play20:48

function receives and will say if there

play20:51

is a username notice I'm using optional

play20:53

chaining here if that's equal to the

play20:56

user.name and remember users what I just

play20:58

defined right here then let's use the

play21:00

double Ampersand because we also need to

play21:03

say

play21:04

prudentials

play21:06

password once again optional chaining

play21:09

equals the user

play21:12

dot password and I'm going to press alt

play21:15

Z to wrap this down so it just wraps all

play21:18

the way down oh and I'm getting a red

play21:20

squiggly here because I didn't Define

play21:21

the password up here under credentials

play21:23

so that's reminding me to go back so

play21:25

thank you typescript we will go back

play21:27

let's finish this if statement quickly

play21:29

and then inside of the if statement if

play21:31

they match we're just going to return

play21:33

the user and then we can have an else

play21:38

and if they don't we're just going to

play21:40

return null so you could make this a

play21:43

ternary statement if you wanted to I

play21:45

think the if statements may be just a

play21:46

little easier for everyone to read let's

play21:48

go ahead and Define the password up here

play21:51

as well which is of course why we had

play21:52

the comma there to begin with so now

play21:54

we'll have our password and this gets

play21:57

defined much the same way so we'll start

play21:59

with our label and the label is going to

play22:01

be

play22:03

password and I'll put a colon there as

play22:05

well because this does appear on the

play22:06

page now the type of input here

play22:09

is a password

play22:10

and then finally we'll put a placeholder

play22:13

you may not want a placeholder for your

play22:15

password field but I'll go ahead and put

play22:16

one and I'm going to say here

play22:19

awesome

play22:21

password now we should not have a red

play22:25

squiggly from typescript because we've

play22:27

defined both username and password on

play22:30

the credentials that are passed in and

play22:33

so then it recognizes both properties

play22:35

let's take a quick scroll down to make

play22:37

sure we've closed out our object and yes

play22:39

everything looks good so the options are

play22:41

now set up let's go back to our route

play22:42

file and import those options here at

play22:45

the top so I'm going to say

play22:47

import

play22:49

options and that's going to come from

play22:52

dot options so now we've got that we can

play22:54

just pass it into our next auth here

play22:56

inside of the route and the routes

play22:58

configured I'm going to press Ctrl B to

play23:00

show the file tree once again over here

play23:02

so we're inside of the route file and

play23:04

now this is configured with options that

play23:06

we defined in the separate file and we

play23:09

could go ahead and start the application

play23:11

now and what we want to do is make a get

play23:13

request because it will already give us

play23:15

some information about our next auth

play23:18

setup so let's go ahead and open a

play23:20

terminal and I'm going to type clear

play23:22

first just to get everything else out of

play23:24

here then type npm run Dev which should

play23:27

start the application and it won't take

play23:29

too long and it will tell us it's

play23:31

running here at localhost 3000. it's

play23:33

already up and running so we can close

play23:35

the terminal now I've got thunderclient

play23:38

installed you could make a git request

play23:40

with Postman you could actually take the

play23:43

URL and paste it into a browser and make

play23:45

a get request that way also so just

play23:48

let's look at what we've got here I've

play23:50

got thunderclient and now I'm going to

play23:52

make a get request and I already have it

play23:54

set up but here's what we want is our

play23:57

HTTP not https just HTTP in our Dev

play24:02

environment colon slash localhost colon

play24:05

Port 3000 then API auth providers so

play24:10

that's where we're going to make our

play24:12

request let's send that get request and

play24:14

let's see what we get back from next

play24:16

auth with our information and it's

play24:18

telling us quite a bit about our setup

play24:20

here so we have GitHub set up as a

play24:22

provider it's type oauth and the sign in

play24:25

url that is generated for us

play24:27

automatically is found at API auth sign

play24:32

in GitHub and then here's the Callback

play24:35

as well now here is the sign in url for

play24:38

credentials API auth sign in credentials

play24:42

and then here's the Callback URL and of

play24:44

course it's type credentials so just by

play24:47

sending a get request to our API auth

play24:50

providers we can get this information

play24:52

from next auth so again just by using

play24:55

the default settings in next auth it

play24:57

does a lot of the heavy lifting for us

play24:59

and that's what I wanted to show today

play25:00

now I'm going to throw a few examples

play25:02

into the front end of our next JS app

play25:04

and then we'll review those as well okay

play25:06

I've got the front end project up and

play25:09

running and I want to show you the

play25:10

behavior of the project before we look

play25:12

at the code notice I'm on the home page

play25:15

right now and it says You shall not pass

play25:17

so I am protecting this page and what I

play25:20

have in this project are three different

play25:22

server components that are all protected

play25:25

in a different way so I want to show you

play25:27

all three ways you can do that I also

play25:29

have a client component so first we're

play25:31

on the home page we're not logged in

play25:33

with GitHub or our credentials so it

play25:35

says you shall not pass now I could try

play25:38

to go to the server page it's protected

play25:40

in a different way so let's try that if

play25:43

we go here we instantly get the sign in

play25:45

page that next auth creates on its own

play25:47

you can see it says your cool username

play25:49

name your awesome password just like we

play25:51

set up for the placeholders we could

play25:53

click here to use oauth to sign in with

play25:55

GitHub or I could sign in here with my

play25:58

username and password and of course I

play25:59

would have to use the ones I hard coded

play26:01

since we're not retrieving those from a

play26:03

user table anywhere so that's another

play26:06

option so that's how the server page

play26:08

here protects itself which is different

play26:10

than the home page and then I have one

play26:12

other server page that right now it's

play26:15

not protected and it's just called extra

play26:16

it's an extra page I made however I want

play26:19

to show the easiest way to apply next

play26:22

auth to your entire site and then it

play26:25

will be protected so let's go back to vs

play26:27

code back in vs code there's one file I

play26:29

haven't created yet so let's do that we

play26:32

want to make it inside the source

play26:33

directory it needs to be at the same

play26:35

level as the app directory so we're

play26:38

going to make it inside the source

play26:39

directory and this is our middleware

play26:41

file so

play26:43

middleware.ts now this runs on the edge

play26:45

and there's some special things about

play26:47

this file if you haven't worked with

play26:49

next JS middleware but you only need to

play26:51

add one line to this file to protect

play26:54

your entire site with next auth so I'm

play26:57

just going to paste this in because I

play26:59

also have a note with it so it says

play27:00

without a defined matcher which we're

play27:02

going to talk about in just a second

play27:04

this one line applies next auth to the

play27:06

entire project so we can save this and

play27:10

now next auth is applied to all pages in

play27:14

our project so let's go back to the

play27:16

browser quickly and now I'm going to

play27:18

reload

play27:20

and what should happen is yes we get the

play27:23

sign in page automatically we're not

play27:25

signed in anywhere if I were to go back

play27:27

to the home page just getting rid of

play27:29

everything else in the URL there just go

play27:31

to localhost 3000 it should also want us

play27:34

to sign in with the GitHub page now

play27:36

because next auth is applying itself to

play27:39

every page let's go back to vs code and

play27:42

we'll also look at how we can just set

play27:43

this for a few select pages with a

play27:47

matcher so now underneath this I'm going

play27:50

to paste in a matcher now I'll press alt

play27:53

Z so we can read all of this which is

play27:54

just a link to the reference about a

play27:57

matcher in the next JS website not the

play28:00

next auth website but this applies next

play28:03

auth only to matching routes so this can

play28:07

be a regex as well and it can exclude so

play28:09

you could look at way more details on

play28:11

this next JS page but with this matcher

play28:14

I've just got an array here that is

play28:16

applying it to the extra route that

play28:18

would be our extra page and I'm imagine

play28:20

we had a dashboard that we wanted to

play28:23

have authentication for for example so I

play28:25

just put in slash dashboard as another

play28:27

example although I don't have a

play28:29

dashboard page in this application now

play28:33

if we go back to vs code or actually if

play28:35

we go back to the browser we should see

play28:37

a difference here so now I'm going to

play28:40

reload the home page once again that is

play28:42

just localhost Port 3000 now we go back

play28:45

to our you shall not pass Behavior

play28:47

instead of the behavior that was applied

play28:49

by putting the auth on the entire site

play28:52

with middleware so now we have the you

play28:54

shall not pass here but now if I go to

play28:56

the extra page it should still be

play28:58

protected remember earlier it wasn't

play29:00

when we had that previous Behavior with

play29:02

the home page so now the middleware has

play29:05

applied next auth to our extra route

play29:08

because it's in that matcher now let's

play29:10

look at the code for the home page and

play29:13

the server page here because they are

play29:15

very similar but they're both applying

play29:17

off in a different way here's the code

play29:18

for our home page come component now

play29:20

notice what we're doing we're importing

play29:22

options that we defined for next auth

play29:24

inside of that route that we have at the

play29:27

beginning there when we started working

play29:28

on the project API slash auth and the

play29:31

catch-all here's our options then we

play29:33

also need to import git server session

play29:35

from next auth Dash next and then I have

play29:39

a user card component that I just

play29:40

imported so I could use it in all of the

play29:42

examples and you could look at that

play29:44

inside of the components directory if

play29:45

you want to now inside of this

play29:48

functional component we await the git

play29:50

server session and we pass in the

play29:52

options that gives us our session so

play29:55

here I'm using kind of logic to

play29:58

determine what we display I'm not doing

play30:00

anything else that's just how I'm

play30:02

protecting the page so if we have a

play30:03

session it shows the user card and if we

play30:06

don't have a session it gives us that

play30:09

message that we were looking at you

play30:10

shall not pass now in comparison let's

play30:13

look at the server route here and the

play30:15

page inside of it it's very much the

play30:18

same but notice I also import reported

play30:20

redirect from next navigation so here we

play30:24

once again await the server session but

play30:27

if we don't have a session we just

play30:29

redirect and we use this callback here

play30:32

inside of the path so API slash auth

play30:35

sign in where our sign in is and then we

play30:38

put the Callback value here the param

play30:40

inside of the URL that is slash server

play30:43

so after we log in it would take us

play30:45

right back to the page that we were

play30:47

wanting to go to and other than that it

play30:50

displays the user card so we're just not

play30:51

using the same logic in the page so two

play30:54

different ways to protect it there if we

play30:56

look at our extra route you'll see

play30:58

inside of the code very very simple here

play31:01

it's not protected at all with this code

play31:04

it doesn't even get the session but

play31:06

because we applied the next auth

play31:09

protection through middleware this page

play31:12

is protected it's just applied in a

play31:14

different way back in the browser now

play31:15

let's talk about the client component

play31:18

now it's worth noting that I don't use

play31:19

use any compliant components that need

play31:22

session data unless it's absolutely

play31:24

necessary so that's just shipping extra

play31:27

code to the client when I can easily

play31:29

request that same data in a server

play31:31

component and not need to ship all of

play31:33

that code to the client so for me server

play31:35

components are usually the bulk of any

play31:37

page and the client components are

play31:39

imported for what I would call Islands

play31:41

of interactivity so the server is

play31:44

usually the parent and then I'm putting

play31:46

some client components where needed

play31:48

inside of it so you don't have to choose

play31:50

server or client whenever possible you

play31:53

just make the server component the

play31:54

parent and import the client component

play31:57

however what we're going to look at is a

play32:00

page completely made up of a client

play32:02

component just as an example here not

play32:04

something I would usually do so let's

play32:06

click client here and you shall see it

play32:09

is also protected let me go ahead and

play32:12

log in just so we can see some behavior

play32:13

from these Pages after I'm logged in

play32:16

and so I just typed in my username and

play32:19

password that we hard coded inside of

play32:21

the code sign in with credentials it

play32:23

says hello Dave and this is a client

play32:26

page if I refresh because we're using

play32:28

that cookie that we described in the

play32:30

docs it's still there and it works just

play32:33

fine notice it takes just a second here

play32:35

on the client page it flashes just a

play32:37

little bit that's a little different

play32:39

Behavior than you'll get on the server

play32:41

page because the server page is rendered

play32:44

and then sent so you don't get that

play32:46

flash so that's something worth noting

play32:47

as well but they both work now we can go

play32:50

to the extra page also that's protected

play32:52

by middleware we can go back to the home

play32:54

page and instead of saying you shall not

play32:56

pass it also says hello Dave and this is

play32:59

the home page so we're clearly logged in

play33:01

if we go to sign out then it takes us to

play33:04

the auto-generated sign out page as well

play33:06

which you can see is at API auth sign

play33:10

out you would just change this to sign

play33:12

in for the auto-generated sign in page

play33:15

so we can sign out here now I'm going to

play33:17

go ahead and log in with GitHub and

play33:19

we'll talk a little bit about what that

play33:21

does as well you're going to need to

play33:22

authorize the use if you haven't done

play33:24

this after you do this the first time

play33:25

it's going to probably save that and you

play33:28

won't have to do that again unless you

play33:30

delete all your data for that site

play33:32

notice I have a image coming in now my

play33:35

image from GitHub as well so we'll talk

play33:37

about that too but let's go back to this

play33:39

client page and discuss how all of this

play33:42

is applied and of course now it says

play33:44

client page so I'm doing the same thing

play33:46

on this page if we refresh this should

play33:48

still keep us logged in and it does back

play33:50

in vs code I'm not showing you the

play33:53

client component code first what I am

play33:55

showing you is the layout page that we

play33:58

have here at the root level along with

play34:00

the root page for the home that's

play34:03

because for the client to access that

play34:06

user data that we get from the session

play34:08

from next auth we need to go ahead and

play34:11

create an auth provider and that is a

play34:13

react context so let's do that first

play34:16

and then of course after we create it it

play34:19

gets imported in here to the layout and

play34:21

we wrap that around everything that we

play34:24

want to send that context to which is

play34:26

just like working with any other react

play34:29

contacts okay so I created a context

play34:31

directory and inside of there I have a

play34:34

file called auth provider.tsx notice

play34:37

it's a client component we say use

play34:40

client then we import the session

play34:42

Provider from next Dash auth react then

play34:46

I went ahead and created the auth

play34:47

provider now it gets children just like

play34:49

the layout component does so you can

play34:52

look at the layout component and see

play34:54

what it's receiving here is just the

play34:56

same as that is and then inside of this

play34:59

we just wrap the children in this

play35:01

session provider that we imported now if

play35:04

we go back and look at the layout TX TSX

play35:07

it might make a little more sense

play35:09

because look this root layout receives

play35:12

the exact same thing as far as children

play35:14

goes then we're just importing the auth

play35:16

provider here and we're wrapping it

play35:18

around everything okay now that we've

play35:20

covered the provider which is only

play35:22

necessary for the client components that

play35:24

need the session let's look inside of

play35:26

this client directory and look at the

play35:28

page because it's a little different

play35:30

than the server components there's a

play35:31

little more work involved as well it

play35:33

says use client here at the top I put in

play35:36

a reminder comment that you need that

play35:38

auth provider to go ahead and get the

play35:41

session data then there's a use session

play35:43

hook that we import from next Dash auth

play35:45

react we're going to go ahead and import

play35:48

redirect as well so we get redirected to

play35:51

that login or sign in page with a

play35:53

callback that says slash client because

play35:55

then we'd want to come back to this page

play35:57

so you always make the Callback value

play35:59

the page that you're on and then inside

play36:02

of you session here notice we get data

play36:04

and we're renaming it session we set

play36:07

required to true and then there's an on

play36:10

unauth account if I could pronounce it

play36:13

on on unauthenticated it there we go I

play36:17

need more coffee this morning and then

play36:19

we redirect of course if we're not

play36:21

signed in so that's what all of that

play36:23

does then if we are signed in well then

play36:25

we're just passing it once again to that

play36:27

same user card that we have right there

play36:29

and note I'm using the same user card

play36:31

inside of those server Pages like the

play36:35

home page or the server page I didn't

play36:37

think I don't think I put it on the

play36:39

extra page that was just very simple but

play36:41

I'm using it inside of this client

play36:43

component too and I've been asked by

play36:44

some can I use a server component inside

play36:46

of a client component you wouldn't want

play36:48

to do that but don't think of this

play36:50

component which is more of a generic

play36:51

component in that regard just think of

play36:53

it as a react component that we're using

play36:55

wherever we need it because this is

play36:58

within a client component I don't have

play37:00

used server or anything at the top of

play37:03

this user card component it's just a

play37:05

component that we can reuse just like a

play37:07

button so we're not really nesting what

play37:09

you would think of as a server component

play37:11

inside of a client component and there

play37:13

shouldn't be a reason to do that either

play37:15

remember what I was advising use the

play37:18

server components as the parents

play37:20

whenever possible and then import the

play37:22

clients and just use those where needed

play37:24

however in this example this is

play37:27

completely a client component because

play37:29

that's what the whole page is I wouldn't

play37:31

normally do that but if you need to do

play37:34

it of course it is possible okay now

play37:36

that we've looked at this code also and

play37:39

we know how the entire app works one

play37:41

other thing to cover and that is just

play37:44

the details on showing that image or

play37:47

anything you would get say you log in

play37:48

with oauth and there's something you

play37:50

want to display so let's go ahead and

play37:52

once again look at the user card because

play37:54

it's displayed in all of these different

play37:56

examples except extra and we'll see what

play38:00

I put in that user card it's in the

play38:02

components directory here we are so

play38:04

after we get the types of course

play38:06

correctly I am using the next image up

play38:09

here because we could get an image from

play38:12

GitHub and so we're saying hello and

play38:15

having a username I also commented out

play38:17

the email you could get the email from

play38:19

GitHub if you want to get the email so I

play38:22

just wanted to leave that code in there

play38:23

in case you want to try it out I am not

play38:25

using that and then we get the image as

play38:28

well and it's coming from GitHub so

play38:30

after you set all of this up and you can

play38:32

see how I'm displaying it down here in

play38:33

the section I just defined the greeting

play38:36

above you could have the email display I

play38:38

defined the user image above and this is

play38:41

what we're of course displaying and

play38:42

here's why I changed out which page type

play38:44

whether it said it was a client type or

play38:46

a server type or the home page or

play38:48

whatever so now that we've looked at all

play38:50

of that the setting that you need to

play38:52

remember about bringing in an image

play38:54

because you could set all of this up and

play38:57

you could still get an error from next

play38:58

JS is when you're bringing in images

play39:01

from an outside Source you need to set

play39:04

those up in the next JS config and I did

play39:07

that here under remote patterns for the

play39:09

image that I would get from GitHub this

play39:12

isn't so much a next auth thing as it's

play39:14

something you need to remember when

play39:16

you're pulling in any image from any of

play39:19

these other oauth providers or anything

play39:21

you might be getting from them like I am

play39:23

getting my image from GitHub back in the

play39:27

browser one last time let's go to the

play39:28

home page and it looks the same except

play39:30

it says home page and of course we do

play39:33

persist to log in if we refresh I am

play39:36

really impressed with next auth and how

play39:39

easy it is to apply especially with the

play39:41

default settings to your next JS project

play39:43

and if you'd like to see more and of

play39:45

course I bet I'm asked about role-based

play39:47

user authorization for say protected

play39:50

routes and things like that or other

play39:52

topics just let me know in the comments

play39:54

because it's very customizable that

play39:56

makes next auth awesome because you can

play39:58

customize it kind of any way you need to

play40:00

use it so just let me know in the

play40:02

comments and I'm looking forward to

play40:04

hearing you and creating more

play40:05

authentication tutorials in the near

play40:07

future remember to keep striving for

play40:09

Progress over Perfection and a little

play40:12

progress every day will go a very long

play40:14

way please give this video a like if

play40:16

it's helped you and thank you for

play40:18

watching and subscribing you're helping

play40:20

my channel grow have a great day and

play40:22

let's write more code together very soon

Rate This
β˜…
β˜…
β˜…
β˜…
β˜…

5.0 / 5 (0 votes)

Related Tags
Next AuthJavaScriptAuthenticationGitHub OAuthJWTWeb DevelopmentSecurityCoding TutorialServerlessReact