Developer protecting his web content

How to protect sensitive content in my static web app?

By Maarten van den HoovenOct 20, 2021

Your static Next.js site is up and running. Now you want to extend it to contain sensitive information that should be displayed only to specific people. How can you do it on a static site?

In this article, I’ll introduce Auth0, explain why I chose it as an authentication provider, and take you through its integration into a static site built with Next.js step by step.

The app that I am developing is built with Next.js and is hosted on Vercel. When I thought about adding additional security to it, I first looked at the platform options. Vercel indeed provides password protection or SSO features, but only for paid accounts. Also, I intended to give access to all my colleagues by default, so I was looking for a more universal approach to the topic.

Auth0 seemed much more promising. It is a cloud-based identity authentication and authorization service for application developers. Auth0 enables users to have access to single sign-on for applications that run on multiple platforms with various identity providers, so they can use Google, Facebook, Azure AD, or other providers that you allow. The service is free of charge for basic use, so you can start directly using it.

1. First let’s create a Next.js app:

npx create-next-app
# or
yarn create next-app

If you run your app, you will see the “Welcome to Next.js” demo app at http://localhost:3000.

Now, imagine that this web app will contain sensitive information that should only be available to a specific audience. For this reason, we are going to add Auth0 to the mix.

2. Install Auth0 SDK in the newly created Next.js app:

npm install @auth0/nextjs-auth0

3. Create an account on https://auth0.com and add a tenant. You can choose your own name and location:

Creating the Auth0 account
Creating the Auth0 account

4. Now that we have an account with a tenant on Auth0, the next step is to add an application on our Auth0 account, which will connect it to our Next.js app. Go to the Auth0 dashboard and create a new Regular Web Applications app.

Auth0 settings
Auth0 settings

Then, make sure to configure the following on the settings page:

    • Allowed Callback URLs
      Should be set to http://localhost:3000/api/auth/callback when testing locally or typically to https://myapp.com/api/auth/callback when deploying your application. After the user authentication, Auth0 will only call back to the URLs you added in this setting.
    • Allowed Logout URLs
      Should be set to http://localhost:3000/ when testing locally or typically to https://myapp.com/ when deploying your application. This is the URL where you go after you log out.

5. You can use several identity providers like Google, Facebook, Apple, Azure AD, and so on. For our application, we will create a new test user with a username and a password:

    • Go to User management -> Users -> Create user
    • Fill in a username and password
Adding a user to Auth0
Adding a user to Auth0

6. Let’s now start the magic and bring the two together. We’ll begin by adding environment variables to the Next.js app. In your local environment, create a .env.local file in the root of your app. In this file, you need to add and adjust the following variables:

AUTH0_SECRET='LONG_RANDOM_VALUE'
AUTH0_BASE_URL='http://localhost:3000'
AUTH0_ISSUER_BASE_URL='https://YOUR_AUTH0_DOMAIN.auth0.com'
AUTH0_CLIENT_ID='YOUR_AUTH0_CLIENT_ID'
AUTH0_CLIENT_SECRET='YOUR_AUTH0_CLIENT_SECRET'

I’ll explain each of these variables below:

AUTH0_SECRET

Create your own secret; you can generate a suitable string using the following command:

node -e "console.log(crypto.randomBytes(32).toString('hex'))"

AUTH0_BASE_URL

This is the URL of your application. For our local environment, it’s http://localhost:3000.

AUTH0_ISSUER_BASE_URL, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET 

You can find these in your Auth0 dashboard under applications -> Default App -> Settings -> Basic information. Don’t forget to add https:// to the AUTH0_ISSUER_BASE_URL.

Settings variables can be found under the application.
Settings variables can be found under the application.

Note: Add the variables also to your other environments like test, acceptance, and production. Click here for an example of how to do this in Vercel.

7. Next, we need to add a dynamic API route handler, which creates several API endpoints as serverless functions. A serverless function (SSR) can, for example, render the /login page from Auth0.
You do this by creating a new folder pages/api/auth and a file [...auth0].js. In this file, add the following piece of code:

import { handleAuth } from '@auth0/nextjs-auth0';

export default handleAuth();

This will automatically listen on the following URLs needed for the authentication tasks:

  • /api/auth/login
  • /api/auth/callback
  • /api/auth/logout
  • /api/auth/me

8. Then we need to wrap our page in the UserProvider component provided by the Auth0 package. You do this by adding the following lines in the _app.js:

import '../styles/global.css'
import { UserProvider } from '@auth0/nextjs-auth0';

function MyApp({ Component, pageProps }) {
  return (
  <UserProvider>
      <Component {...pageProps} />
    </UserProvider>
  );
}

export default MyApp

9. The last step is to add authentication to the front end. You can make the whole app restricted, configure specific pages that need authentication, or handle visibility of specific elements based on user authentication status. In my case, I only have one page (index.js) needing authentication, and that can be achieved with the withPageAuthRequired function. You need to reference the function and wrap your page in it:

import { withPageAuthRequired } from '@auth0/nextjs-auth0';

export default withPageAuthRequired(function Home() {

If you now go to http://localhost:3000/ you will not see the “Welcome to Next.js” demo app, but you will get a login prompt from Auth0:

Auth0 login prompt
Auth0 login prompt

So, let’s try our created test user and fill in the credentials. If everything is correctly configured, we will now get back to our app and see “Welcome to Next.js!” Congratulations, you have successfully added authentication to your Next.js app!

With the authentication, you also get the useUser function that enables you to protect specific content or use profile data like a username within the app. Here’s an example of how to add a simple login/logout link to your application:

// pages/index.jsx
import { useUser } from '@auth0/nextjs-auth0';

export default () => {
  const { user, error, isLoading } = useUser();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>{error.message}</div>;

  if (user) {
    return (
      <div>
        Welcome {user.name}! <a href="/api/auth/logout">Logout</a>
      </div>
    );
  }
  return <a href="/api/auth/login">Login</a>;
};

You have a lot more possibilities with Auth0—for a full list, visit the official documentation that contains many examples and best practices.

Conclusion

I showed you how to add an authentication and authorization layer to a Next.js app. I hope you enjoyed this experience and were pleasantly surprised by the smoothness of the integration. This also illustrates the power of front-end development these days and shows how easy it is to use tools like Auth0 for doing complex functionalities in a couple of minutes.

The full code example of this tutorial is available on GitHub, and if you’d like to join our community, you can find us on Discord.

Written by
Maarten van den Hooven

I love coding, talking to the customers, and making them enthusiastic about a great product. As Presales Engineer, I can use my technical know-how in combination with my communication skills to help businesses find the best solution to their challenges.

More articles from Maarten

Subscribe to Kontent Newsletter

Stay in the loop. Get the hottest updates while they’re fresh!