Your Ultimate Guide to Next.js Authentication

This tutorial describes Next.js authentication patterns and helps you learn step-by-step how to authenticate a Next.js application.
profile
Emadamerho-Atori NefeFirst published: 2022-01-13Last updated: 2025-06-25
guest-post,nextjs-authentication-guide
Table of Contents

What is Authentication?

In this article, you'll learn about authentication in Next.js and how you can authenticate Next.js applications with LoginRadius.

Note: An understanding of React, Hooks, and Next.js is beneficial to follow this tutorial.

What is Authentication?

Authentication is the process of validating that an individual is who they claim to be. Authentication is an essential feature for applications, particularly those that store user data.

You should not mistake authentication for authorization. Authorization is the process of verifying that whether a user has required permission to access an asset or data set.

Authentication deals with identifying a user, while authorization checks what resources or data an authenticated user has permission to access.

Some of the methods used to implement authentication are:

  • Username/email and password
  • Fingerprint
  • Face recognition
  • Security questions
  • One time pins (OTPs)
  • Magic links

Should You Build Your Authentication System or Use a Third-party Solution?

Authentication is one of the most critical parts of an application’s security, so you should address it adequately.

A few aspects you should consider when assessing if you should build your authentication system or use a third-party solution:

  • Progressive Enhancements: Security systems require frequent enhancements and upgrades to keep users safe from evolving threats and techniques. How much time and resources can you commit to keeping your security system up-to-date with the latest countermeasures to safeguard data and access against emerging threats?

  • Identity Provider Support: How many identity providers do you plan to support, if any? With third-party solutions, you can authenticate users with email/password as well as identity providers such as Google, Github, Facebook, and more. Third-party solutions are always working hard to add support to even more providers. They also provide other authentication methods like Magic Link for passwordless authentication.

    Can you build an authentication system that allows users to use their preferred authentication method, or will they be restricted?

  • Advanced Security Features: Security and authentication go beyond email/password sign-in. Most third-party solutions provide necessary features, such as email confirmation, two-factor authentication (2FA), etc.

    You should let the security experts such as LoginRadius do what they do best while focusing on your main tasks — building excellent applications.

Considering these factors, it's pretty easier to rely on a third-party solution, and it's also cheaper and more secure than building your own authentication system.

What is LoginRadius?

Loginradius is the world's first no-code identity platform. It is a simple, implementable solution for adding user authentication and authorization to your website.

LoginRadius provides no-code services for authorization, authentication, account security, and much more. It has several interesting features, and some of them are:

Understanding Next.js Authentication Patterns

Next.js offers two authentication patterns — client-side and server-side authentication.

Client-Side Authentication

With client-side authentication, the authentication logic and user redirection are done in the browser. The page component fully loads before the redirect logic is executed.

When this authentication approach is used, developers usually use a loading indicator to indicate to the user that a process is running in the background. The loading indicator helps boost user experience. If the user’s authentication fails, redirect the user to a login page.

The following example shows how to handle client-side redirects:

1import { useEffect } from "react" 2import { useRouter } from "next/router" 3import authService from "auth-service" //imaginary auth service 4export default function ProtectedPage() { 5const router = useRouter() 6useEffect(() => { 7const authUser = authService.getUser() 8// if there is no authenticated user, redirect to login page_ 9 10if (!authUser) { 11 router.push("/login") 12} 13 14}, []) 15return ( 16<> 17<h1>Welcome {user.name}. This is a protected page</h1>` 18</> 19) 20}

The above code snippet handles client-side redirects in the browser using next/router. It also uses an imaginary authentication service, auth-service, for illustration purposes. You’ll work with LoginRadius later in this tutorial.

It checks if there is an authenticated user with the authService.getUser() method in the useEffect. If there is none, it redirects the user to the /login page using Next.js’s router object.

This is a simple illustration of client-side authentication and redirection.

Server-Side Authentication

With server-side authentication, you can redirect a user from, say, pages/profile to pages/login. When non-authenticated users try to access a protected page, they are redirected to a login page. All of this is done on the server — before the request reaches the browser.

A benefit of this pattern is that non-authenticated users do not see flashes of unauthenticated content before they are redirected.

The following example below shows how to handle server-side redirects:

1export default function ProtectedPage({ user }) { 2 return ( 3 <> 4 <h1>Welcome {user.name}. This is a protected page</h1> 5 </> 6 ) 7} 8export const getServerSideProps = async context => { 9const { user } = authService.getUser(context.req) 10// if there is no authenticated user, redirect to login page 11 12if (!user) 13 return { 14 props: {}, 15 16 redirect: { destination: "/login" }, 17 } 18 19 return { props: { user } } 20} 21 22}

Using getServerSideProps enables rendering pages on the server. You can take advantage of that to also handle the redirection on the server.

The above code snippet uses the authService.getUser() method to get the authenticated user’s object. If there is no user, it returns an object with a redirect object. The redirect object contains a destination key, where you can put the page you want to redirect the user to, which is your application’s login page.

Now that you’ve understood the authentication patterns available, let’s see how to authenticate a Next.js application with LoginRadius.

Authenticating Next.js Apps with LoginRadius

The steps below highlight how you can integrate and authenticate your Next.js applications with LoginRadius:

Create a LoginRadius Account

You should create an account to get started with LoginRadius. There is a free plan you can start with.

Get Account Credentials

Now that you have an account, you should get the credentials for your appName and apiKey from the dashboard. You'll need them later to use the React SDK.

Start a New Next.js Application

Run the following command in your terminal to create a new Next.js application:

1npx create-next-app <name-of-project> 2//or 3yarn add create-next-app <name-of-project>

Install LoginRadius React SDK

Next, install the React SDK into the project:

1```javascript 2npm install loginradius-react 3//or 4yarn add loginradius-react 5```

Integrate the React SDK

You need to wrap the root component with the SDK’s authentication provider.

You also need to pass the account credentials to the provider. You can get these credentials from your LoginRadius account dashboard.

Navigate to pages/_app.js and update it with the code below:

1import Head from "next/head" 2import { LRAuthProvider } from "loginradius-react" 3import { ChakraProvider } from "@chakra-ui/react" 4import Layout from "../layout" 5import "../styles/globals.css" 6function MyApp({ Component, pageProps }) { 7return ( 8<> 9<Head> 10<title>Loginradius Next</title> 11</Head> 12 &#x3C;LRAuthProvider 13 appName="your-app-name" 14 apiKey="your-api-key" 15 redirectUri={"http://localhost:3000/"} 16 > 17 &#x3C;ChakraProvider> 18 &#x3C;Layout> 19 &#x3C;Component {...pageProps} /> 20 &#x3C;/Layout> 21 &#x3C;/ChakraProvider> 22 &#x3C;/LRAuthProvider> 23&#x3C;/> 24 25) 26} 27export default MyApp

The above code snippet imports the LRAuthProvider component from loginradius-react. It passes the appName and apiKey taken from the LoginRadius account dashboard earlier to LRAuthProvider. It also sets the redirectUri to http://localhost:3000/.

The redirectUri is the callback URL where you want to redirect users after being authenticated. You should whitelist the redirect_uri in your LoginRadius account dashboard. Localhost URLs are whitelisted by default.

Now that you've integrated the SDK, let’s add the authentication functionality.

Add Login and Logout Functionality

Your users should be able to log in and out of our application, so let’s set that up.

We will add the log in and log out functionality to a Nav component. Let’s set up the component.

Create a layout folder in the root directory, and create a Nav.js file there. Add the following code to Nav.js:

1import { Button, Flex, Stack } from "@chakra-ui/react" 2import { useLRAuth } from "loginradius-react" 3export default function Nav() { 4const { loginWithRedirect, logout } = useLRAuth() 5return ( 6<Flex> 7<Stack spacing={[6, 8]}> 8<Button onClick={() => loginWithRedirect()}>Login to continue</Button> 9<Button onClick={() => logout()}>Log out</Button> 10</Stack> 11</Flex> 12) 13}

Here, Chakra UI is used for UI components.

First, it imports the useLRAuth hook from the SDK. Next, it accesses the loginWithRedirect and logout methods from the useLRAuth hook.

Then, it passes loginWithRedirect and logout to the login and logout buttons’ onClick event handlers, respectively.

Having created the Nav component, we need to create the Layout component we mentioned earlier.

Create an index.js file in the layout folder, and paste the code below:

1import { Box } from "@chakra-ui/react" 2import Nav from "./Nav" 3export default function Layout({ children }) { 4return ( 5<Box h="100vh" bg="green.50"> 6<Nav /> 7<Box>{children}</Box> 8</Box> 9) 10}

With that, you've added authentication to your application. However, you need a way to track the authentication state. You need to know if there is a logged-in user and do something with that information.

Tracking Authentication State

The SDK also provides error and user objects, along with isLoading and isAuthenticated booleans. You'll use these to track the authentication state.

You can access information about an authenticated user, such as their email address, from the user object. If any, you can display error messages from the error object.

isAuthenticated returns true if there is an authenticated user and false if there is not.

We are currently rendering both the login and logout buttons in the Nav component. However, we don’t want that. We want to display the login button when there is no authenticated user and logout when there is an authenticated user.

Let’s update the Nav.js file with the code below to fix that:

1import { Button, Flex, Stack } from "@chakra-ui/react" 2import { useLRAuth } from "loginradius-react" 3export default function Nav() { 4const { isAuthenticated, user, loginWithRedirect, logout } = useLRAuth() 5return ( 6<Flex as="nav"> 7<Stack spacing={[6, 8]}> 8{!user && ( 9<Button onClick={() => loginWithRedirect()}>Login to continue</Button> 10)} 11 {isAuthenticated &#x26;&#x26; user &#x26;&#x26; ( 12 &#x3C;Button onClick={() => logout()}>Log out&#x3C;/Button> 13 )} 14 &#x3C;/Stack> 15&#x3C;/Flex> 16 17) 18}

We conditionally display the login and logout buttons based on the authentication state.

If there is a logged-in user, we want to redirect them to the profile page.

Navigate to pages/index.js file and update it with the code below:

1import { useEffect } from "react" 2import { useRouter } from "next/router" 3import { useLRAuth } from "loginradius-react" 4import { Button, Heading, VStack, Center } from "@chakra-ui/react" 5export default function Home() { 6const { isLoading, isAuthenticated, error, user } = useLRAuth() 7const router = useRouter() 8useEffect(() => { 9if (user && isAuthenticated) { 10router.push("/profile") 11} 12}, [router, user, isAuthenticated]) 13if (isLoading) { 14return <div>Loading...</div> 15} 16if (error) { 17return <div>Oops... {error.message}</div> 18} 19return ( 20<Center pt={10}> 21<VStack spacing={[6, 8]}> 22<Heading as="h2">Welcome</Heading> 23<Text fontSize="3xl">Login to continue</Text> 24</VStack> 25</Center> 26) 27}

Let’s break down the above code snippet:

  • In the useEffect, it checks if there is a user object and if isAuthenticated is true. If these conditions are true, it redirects the user to their profile page. These conditions will only be true when the user has logged in. You'll set up the profile page later.
  • It checks if the page is loading using the isLoading boolean. If true, it displays “loading…”. In a production-ready application, you would display a loading spinner.
  • If there is an error during the authentication process, it accesses the message from the error object and displays it to the user.
  • Finally, return some JSX.

Displaying Authenticated User Data

You have to display information about the authenticated user. Let’s set that up. Create a profile.js file in the pages directory and paste the code below:

1import { Box, Center, Heading } from "@chakra-ui/react" 2import { useLRAuth } from "loginradius-react" 3export default function Profile() { 4const { user, isLoading, isAuthenticated } = useLRAuth() 5if (isLoading) { 6return <div>Loading...</div> 7} 8if (isAuthenticated) { 9return ( 10<Box> 11<Center mt={10}> 12<Heading a="h2"> 13Welcome to your profile {user.Email[0].Value} 14</Heading> 15</Center> 16</Box> 17) 18} 19}

You should display a user’s information if they're authenticated. Here, you check that they're authenticated with the isAuthenticated hook. If they're authenticated, return some JSX and display the user’s email address.

Protecting a Route

You can create protected routes to ensure only authenticated users can access those routes.

1import { withAuthenticationRequired } from "loginradius-react" 2const Profile = () => { 3if (isAuthenticated) { 4return ( 5<Box 6...markup goes here 7</Box 8) 9} 10} 11export default withAuthenticationRequired(Profile, 12//Show a message while the user waits to be redirected to the login page. 13onRedirecting: () => ( 14<div>Redirecting you to LoginRadius awesome Login page</div> 15), 16});

Here, the code snippet uses the withAuthenticationRequired higher-order component to wrap the Profile component. With this, anytime an unauthenticated user tries to access the /profile route, they'll be redirected to LoginRadius’s login page and then back to /profile after they log in.

The image below shows an authenticated user's profile page.

An authenticated user's profile page

Conclusion

In this tutorial, you have learned about user authentication and understood whether you should develop an authentication system in-house or use a modern identity platform like LoginRadius.

Then, you have briefly learned different authentication patterns available in Next.js. And you step-by-step understood how to authenticate Next.js applications with LoginRadius’s React SDK.

A working version of the code used in this tutorial is available on Github.

Emadamerho-Atori Nefe
By Emadamerho-Atori NefeA frontend developer and UI enthusiast who loves learning new things, creating technical content, and sharing his knowledge with others. In his pastime, he reads manga, watches Anime, and writes poems.
Featured Posts

How to Implement JWT Authentication for CRUD APIs in Deno

Multi-Factor Authentication (MFA) with Redis Cache and OTP

Introduction to SolidJS

Build a Modern Login/Signup Form with Tailwind CSS and React

Implement HTTP Streaming with Node.js and Fetch API

NestJS: How to Implement Session-Based User Authentication

NestJS User Authentication with LoginRadius API

How to Authenticate Svelte Apps

Flutter Authentication: Implementing User Signup and Login

How to Secure Your LoopBack REST API with JWT Authentication

Node.js User Authentication Guide

Your Ultimate Guide to Next.js Authentication

Local Storage vs. Session Storage vs. Cookies

How to Secure a PHP API Using JWT

Using JWT Flask JWT Authentication- A Quick Guide

Build Your First Smart Contract with Ethereum & Solidity

What are JWT, JWS, JWE, JWK, and JWA?

How to Build an OpenCV Web App with Streamlit

32 React Best Practices That Every Programmer Should Follow

How to Build a Progressive Web App (PWA) with React

Bootstrap 4 vs. Bootstrap 5: What is the Difference?

JWT Authentication — Best Practices and When to Use

What Are Refresh Tokens? When & How to Use Them

How to Upgrade Your Vim Skills

How to Implement Role-Based Authentication with React Apps

How to Authenticate Users: JWT vs. Session

How to Use Azure Key Vault With an Azure Web App in C#

How to Implement Registration and Authentication in Django?

11 Tips for Managing Remote Software Engineering Teams

Implementing User Authentication in a Python Application

Add Authentication to Play Framework With OIDC and LoginRadius

Share On:
Share on TwitterShare on LinkedIn