Den Dribbles

Implementing Simple Auth To Your Next.js Website using Next.js Auth

November 16, 2020

Password protection for deploys can be a costly payment when hosting websites, particularly when you want to protect branch deployments.

In today’s tutorial, I am going to show you how you can set up your own simple authentication protection on these branches using Next.js 10 and Next.js Auth.

Getting Started

# Create simple-auth-example
npx create-next-app simple-auth-example
cd simple-auth-example
# Install packages required
npm i next-auth --legacy-peer-deps
# Create required auth route
mkdir pages/api/auth
touch "pages/api/auth/[...nextauth].js"
# We'll also create a private page we a basic example
touch pages/private.js

Setting up the API

In pages/api/auth/[...nextauth].js, add the following:

import NextAuth from "next-auth"
import Providers from "next-auth/providers"

const isCorrectCredentials = credentials =>
  credentials.username === process.env.NEXTAUTH_USERNAME &&
  credentials.password === process.env.NEXTAUTH_PASSWORD

const options = {
  // Configure one or more authentication providers
  providers: [
      // The name to display on the sign in form (e.g. 'Sign in with...')
      name: "Credentials",
      // The credentials is used to generate a suitable form on the sign in page.
      // You can specify whatever fields you are expecting to be submitted.
      // e.g. domain, username, password, 2FA token, etc.
      credentials: {
        username: { label: "Username", type: "text", placeholder: "jsmith" },
        password: { label: "Password", type: "password" },
      authorize: async credentials => {
        if (isCorrectCredentials(credentials)) {
          const user = { id: 1, name: "Admin" }
          // Any object returned will be saved in `user` property of the JWT
          return Promise.resolve(user)
        } else {
          // If you return null or false then the credentials will be rejected
          return Promise.resolve(null)
          // You can also Reject this callback with an Error or with a URL:
          // return Promise.reject(new Error('error message')) // Redirect to error page
          // return Promise.reject('/path/to/redirect')        // Redirect to a URL

export default (req, res) => NextAuth(req, res, options)

We are going to use NEXTAUTH_USERNAME and NEXTAUTH_PASSWORD to set up our basic environment variables.

The above will make a comparison, and if that comparison is correct, we’ll return the user object which will just be a name of admin and ID of 1.

Setting up a private page

In pages/private.js, add the following:

import React from "react"
import { signIn, useSession } from "next-auth/client"

export default function Page() {
  const [session, loading] = useSession()

  if (loading) {
    return <p>Loading...</p>

  return (
      {session ? (
        <p>Super secret page!</p>
      ) : (
          <p>You are not permitted to see this page.</p>
          <button onClick={signIn}>Sign in</button>

Here we will use the useSession hook to determine if we are logged in, while using signIn from the next-auth/client library to given an option for the user to sign in.

Updating pages/index.js and pages/_app.js

Finally, let’s update our base page:

import React from "react"
import Link from "next/link"
import { signIn, signOut, useSession } from "next-auth/client"

export default function Page() {
  const [session, loading] = useSession()

  if (loading) {
    return <p>Loading...</p>

  return (
      {!session && (
          Not signed in <br />
          <button onClick={signIn}>Sign in</button>
      {session && (
          Signed in as {} <br />
          <button onClick={signOut}>Sign out</button>
        <Link href="/private">
          <a>Go to private page</a>

This will do similar to our private page based on the session.

As for pages/_app.js we will ensure our auth provider is there:

import { Provider } from "next-auth/client"

export default function App({ Component, pageProps }) {
  return (
    <Provider session={pageProps.session}>
      <Component {...pageProps} />

That is all we need for the code setup!

Setting environment variables

For local development, we can add env vars to the .env.local file. Add the following now:


Here we set the username and password required for the auth and the apps URL (here it is just localhost).

Perfect, now we can see things in action!

Exploring the website

If we run npm run dev, it will run next dev through a package.json script and start the website on localhost:3000.

Basic page requiring login

The page as it sits currently does not have access, and so it displays our sign in message.

Regardless of access, there will be a link to click through to our /private page where all the content is private.

If we select that, we will see that we do not have permission.

Access denied for the private page

If we now decide to click sign in, we will get a sign in page provided by Next.js Auth.

Sign in page provided by Next.js Auth

Writing in our username and password as we have set it in the environment variable will result in us being redirected to the previous page with access.

Access allowed

Success! We have managed to add simple, basic authentication to our Next.js application.

You can try out the project being hosted on Vercel.

Resources and further reading

  1. Live project
  2. Code repo
  3. Next.js Auth
  4. Next.js Auth - credentials

Image credit: Chris Yang

Related Articles

December 09, 2020

See how you can dynamically create UIs based on React State using dynamic imports, Next.js 10 and React State

December 02, 2020

Have you ever wanted to build a UI Component Library with TypeScript and React? This blog post will take you through a straightforward set up that uses the bare minimum to get a working component library that you can re-use across your different React projects.

November 08, 2020

This blog post will explore the new Next.js Image component for an optimised image experience on the web.

November 08, 2020

This blog post will explore the new internationalised routing in Next.js 10 and how you can use this to your advantage with react-intl for React.js

November 07, 2020

Learn how to create a test Stripe example, update that example and deploy to Vercel for a Stripe payment gateway, React 17, TypeScript 4 and Next.js 10

November 06, 2020

See a roundup of my look into Vercel's new analytics feature that you can enable on a Vercel project and see how I used GTMetrix to help push some numbers.

November 05, 2020

Learn how to deploy the base Next.js 10 app with the Vercel CLI and/or the Vercel GitHub Integration

November 04, 2020

Learn how to export static HTML from a Nextjs 10 project to host

October 28, 2020

Updating my previous post on using Create React App with Snowpack for the latest versions and NPM 7

August 18, 2020

Look at how you can create your first ESLint rule and apply it to a working application

A personal blog on all things of interest. Written by Dennis O'Keeffe, Follow me on Twitter