Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Peter Jacxsens
Peter Jacxsens

Posted on • Edited on

     

4/ NextAuth with GoogleProvider: signing in

In this chapter we're going to installNextAuth and setup a basic example with Google provider. Note that ourNext app only has a single page, the home page (/app/index) and a single component<Navbar /> that has one link to the home page. The finished code for this chapter is available ongithub (branch: basicgoogleprovider).

Install

InstallNextAuth in thefrontend folder:

npm i next-auth
Enter fullscreen modeExit fullscreen mode

Next, we setup a route handler forNextAuth. We create aroute.ts file in a new foldersrc/app/api/auth/[...nextauth]/route.ts. The[...nextauth] folder is a catch all route inNext. This means that all requests toapi/auth or to for exampleapi/auth/local/register will be handled by our newly createdroute.ts route handler. Put this inside the handler:

// frontend/src/app/api/auth/[...nextauth]/route.tsimportNextAuthfrom'next-auth';import{authOptions}from'./authOptions';consthandler=NextAuth(authOptions);export{handlerasGET,handlerasPOST};
Enter fullscreen modeExit fullscreen mode

Create theauthOptions.ts file that gets referred to above.

Note here:authOptions is just an object with configuration and customizations properties. Most tutorials just write it as an object literal in the route handler. However, when runningNext build it gave me a TypeScript error at a certain point. One of theNextAuth authors suggested to place theauthOptions in a separate file. This did solved the problem and that is why we are puttingauthOptions in a separate file.

// frontend/src/app/api/auth/[...nextauth]/authOptions.tsimport{NextAuthOptions}from'next-auth';importGoogleProviderfrom'next-auth/providers/google';exportconstauthOptions:NextAuthOptions={providers:[GoogleProvider({clientId:process.env.GOOGLE_CLIENT_ID??'',clientSecret:process.env.GOOGLE_CLIENT_SECRET??'',}),],};
Enter fullscreen modeExit fullscreen mode

What happens here: we add our first provider to the providers list. We then configureGoogleProvider that we import fromNextAuth. The client id and secret come from the.env file that we wrote inchapter 1.

By the way, to read theNextAuth docs on this, just googleNextAuth provider google and that will lead you to thedocs page where you will see this setup.

Finally, add following lines to your .env.local file: (This isn't strictly required in development but will prompt warnings in your terminal.)

# frontend/.env.localNEXTAUTH_URL=http://localhost:3000NEXTAUTH_SECRET=EDITME->somesecret
Enter fullscreen modeExit fullscreen mode

WhereNEXTAUTH_SECRET is a secret you need to generate. For windows user, open bash and enter following:

openssl rand -base64 32
Enter fullscreen modeExit fullscreen mode

Copy the return string and paste it into your.env.local file. Other platforms I'm not sure, look it up.

Our first login with GoogleProvider in NextAuth

We are now ready for our first login. Yes, it is that easy. We create a login button:

// src/components/header/SignInButton.tsx'use client';import{signIn}from'next-auth/react';exportdefaultfunctionSignInButton(){return(<buttontype='button'className='bg-sky-400 rounded-md px-4 py-2'onClick={()=>signIn()}>      sign in</button>);}
Enter fullscreen modeExit fullscreen mode

Firstly, we make it a client component because our button needs an event handler. In the onClick event we passsignIn. This is a function fromNextAuth that when called will start the sign in procedure.

We only have our homepage right now but that is ok. In our currentNextAuth configuration there is no custom login page andNextAuth will redirect us to aNextAuth default login page. We will customize this later with our own page. Let's run ourNext frontend and click the sign in button. We are redirected tohttp://localhost:3000/api/auth/signin?callbackUrl=http%3A%2F%2Flocalhost%3A3000%2F (with callback parameter to home page):

default signin page nextauth

This is the default login pageNextAuth provides and there are some things we need to say about this:

  1. Obviously, it not a nice design.
  2. You cannot change this page with f.e. other styling.
  3. If you're not coding along you won't know this but clicking the login button triggered a full page reload (F5 reload).

Conclusion, this is not something you would want to use in production but here, it does serve some purpose. Let's click theSign in with Google link and see what happens:

  • We are redirected tohttps://accounts.google.com/o/oauth2/v2/auth/... (only on first login)
  • We are asked what google account we want to use. (only on first login)
  • We are asked if we want to login to -appname- and that means that Google will share following data -some data-. (only on first login) (These align with the settings we made inchapter 1, Google OAuth setup)
  • On clicking continue we are redirected to our frontend homepagelocalhost:3000.

If we logout and login again (which we can't yet), the first 3 steps will be skipped. This is just the classic authentication flow with Google as I'm sure we've all done.

But, it works, so yay! What we're missing is feedback. Are we logged in or not? We are but we don't know and that is our next step.

NextAuth Session

We are now signed in usingNextAuth. Practically, that means thatNextAuth verified us with Google and then set some cookies, one with aJWT token. But, we don't have to worry about cookies.

NextAuth provides us with 2 ways to verify if a user is logged in:

  1. For client components: theuseSession hook.
  2. For server components: thegetServerSession function.

NextAuth useSession hook

useSession is a hook, so you can only use it in client components. It's just a hook, so you call it (no parameter required) and it returns an object that you destructure.

'use client';import{useSession}from'next-auth/react';const{data:session,status,update}=useSession();
Enter fullscreen modeExit fullscreen mode

For now we ignore status and update and focus on the data property that we rename to session. Our session will be either null/undefined (not logged in) or an object of type DefaultSession:

{user?:{name?:string|nullemail?:string|nullimage?:string|null}expires?:string}
Enter fullscreen modeExit fullscreen mode

This session interface can and will be customized, meaning we put more data on it.

NextAuth getServerSession() function

getServerSession is an async function that you use in server components or route handlers.

  • It takes one parameter, theauthOptions object that we pass in ourapp/api/auth/[...nextAuth]/route.ts route handler.
  • It returns either null (not logged in) or the default session from just above.
  • Notice the async and await keywords!
import{getServerSession}from'next-auth';import{authOptions}from'@/app/api/auth/[...nextauth]/authOptions';exportdefaultasyncfunctionMyComponent(){constsession=awaitgetServerSession(authOptions);// ...}
Enter fullscreen modeExit fullscreen mode

Let's add this to our code to get a better feel for it. Firstly though, to runuseSession, we have to wrap our entire app into a provider thatNextAuth gives us.

NextAuth SessionProvider

Things get a bit complicated here but in the end it is just a configuration so don't worry about it too much.

The problem is that theSessionProvider thatNextAuth gives us is a client component because it usesReact hooks. But, sinceNextAuth v4 is getting a bit older, it doesn't use theuse client directive. This makesNext throw an error.

You can read more about this problem and how to solve it in theNext docs. The solution is to importSessionProvider in a client component and immediately export it like this:

// frontend/src/app/component/Provider.tsx'use client';import{SessionProvider}from'next-auth/react';exportdefaultSessionProvider;
Enter fullscreen modeExit fullscreen mode

We now can use this<Provider /> component to wrap around our app inside our root layout file:

// frontend/src/app/layout.tsx//...importNavBarfrom'@/components/header/Navbar';import{SessionProvider}from'next-auth/react';import{getServerSession}from'next-auth';import{authOptions}from'./api/auth/[...nextauth]/authOptions';//...exportdefaultasyncfunctionRootLayout({children,}:Readonly<{children:React.ReactNode;}>){constsession=awaitgetServerSession(authOptions);return(<htmllang='en'><bodyclassName={`${inter.className}  px-2 bg-zinc-200`}><SessionProvidersession={session}><divclassName='max-w-6xl mx-auto'><NavBar/><mainclassName='my-4'>{children}</main></div></SessionProvider></body></html>);}
Enter fullscreen modeExit fullscreen mode

Note how we made RootLayout async but again, don't worry to much about this, in the end it is just configuration. We continue in the next chapter.


If you want to support my writing, you candonate with paypal.

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
anime_king_d345ba78066592 profile image
Anime King
  • Joined

Image description
here shouldn't the highlighted line be
import SessionProvider from "./components/Provider"

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Front-end developer
  • Location
    Belgium
  • Education
    self taught
  • Joined

More fromPeter Jacxsens

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp