Authentication using NexAuth in NextJS

YashYash
4 min read

Authentication in NextJS has been made very simple by the next-auth library, in this post we will go through on how to setup authentication in your NextJS 14 application. We will not be using NextJS 15 because it is not stable yet.

I will not go through the installation steps of Next project, we will start by installing next-auth library

npm i next-auth

Once this is done, we have to create a .env.local file in the project root to store our variables

NEXTAUTH_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
NEXTAUTH_URL="http://localhost:3000"

GITHUB_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
GITHUB_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

GOOGLE_CLIENT_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
GOOGLE_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Here, the NEXTAUTH_SECRET can be anything, it is used for encryption, the NEXTAUTH_URL is used to redirect the user after the user is signed in. The GITHUB_ID, GITHUB_SECRET, GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are the credentials that are to be obtained from those particular websites.

Note: While setting the credentials in Github, Google and other such auth providers, we have to set the callback url to http://localhost:3000/api/auth/callback/google, here the http://localhost:3000 is to be replaced with your domain and the callback/google is to be replaced with your provider name such as github, twitter, etc.

After this, we have to make a file with the path /lib/authOptions.ts, it will be used to export the auth options that we are using in the app

import { NextAuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";

export const authOptions : NextAuthOptions = {
    providers: [
      GithubProvider({
        clientId: process.env.GITHUB_ID as string,
        clientSecret: process.env.GITHUB_SECRET as string,
      }),
      GoogleProvider({
        clientId: process.env.GOOGLE_CLIENT_ID as string,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
      }),
    ],
  }

Here, we are importing the values from our .env.local file that we made earlier.

Moving forward, we need to make one more such file in the path /src/app/api/auth/[…nextauth]/route.ts which will be used for our client side authentication

import NextAuth from "next-auth";
import { authOptions } from "../../../../../lib/authOptions";
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

In this file, we are importing the authOptions that we exported.

Moving forward, we need to make a SessionWrapper component which will be used to as a provider in our frontend, due to this component we can use the hooks provided by NextAuth anywhere in our application.

This is the component that I created in the path, /components/SessionWrapper.tsx, the path does not matter, but it should be a tsx or jsx component.

"use client";

import { SessionProvider } from 'next-auth/react';
import React from 'react'

function SessionWrapper({children} : {children: React.ReactNode}) {
  return (
    <SessionProvider>
        {children}
    </SessionProvider>
  )
}

export default SessionWrapper

Now we have to use this wrapper in our layout.tsx file in /src/app/layout.tsx

...
 return (
    <SessionWrapper>
      <html lang="en">
        <body className={inter.className}>{children}</body>
      </html>
    </SessionWrapper>
  );
...

Now, we are good to use the authentication anywhere in our app, let us see how it is done.

We are provided with a useSession() hook by next-auth which can be used to get a session variable

const {data: session} = useSession();

This variable returns false if the user is not signed in, and it contains the user data if the user is logged in.

So we can use this information to build an interface

if (session) {
    return (
      <>
        <p>You are logged in as</p>
        <p>{session.user?.name}</p>
        <p>{session.user?.email}</p>
      </>
    );
  }
  return (
    <>
      <p> You are not logged in please, login</p>
    </>
  );

But, you may ask how do I sign-in and sign-out? NextAuth provides very simple functions for that as well, we just have to import them and use in our app

import { signIn } from 'next-auth/react';
...
return(
<>
    <p>You are not logged in please, login</p?>
    <br />
    <p onClick={() => signIn("github")}>Github</p>
    <br />
    <p onClick={() => signIn("google")}>Google</p>
</>
);

The signOut method is also provided which can be used directly.

Now, we are done with the basics of frontend auth, now for the backend side authentication.

This is an example of an api route which returns the user information.

import { getServerSession } from "next-auth";
import { NextRequest, NextResponse } from "next/server";
import { authOptions } from "../../../../lib/authOptions";

const GET = async (request: NextRequest) => {
    const session = await getServerSession(authOptions);

    if(!session){
        return NextResponse.json({
            "failed": "No session found"
        })
    }

    return NextResponse.json(session);
}

export {GET};

The response is something like this:

{
  "user": {
    "name": "Yash",
    "email": "hi@yassh.in",
    "image": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.url.com"
  }
}

This is enough to get you started with authentication in NextJS 14 using NextAuth library.

0
Subscribe to my newsletter

Read articles from Yash directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yash
Yash