Next.js React Authentication

Add Custom Login, Registration, User Settings to Your Next.js & React Single Page Application (SPA)

Aeneas Rekkas - November 09, 2021

Time to read: 6 min

Add authentication and user management to your Next.js React app using the new Next.js Edge Runtime and the Ory Kratos open source project!

Ory Kratos Open Source Identity Platform

Ory Kratos is a full-featured, free, and open source authentication and identity management platform. It supports multi-factor authentication with FIDO2, TOTP, and OTP; Social Sign In, custom identity models; registration, profile management, account recovery, administrative user management and so much more! In contrast to other identity systems, Ory Kratos enables you to build your own login, registration, account settings, account verification (e.g. email, phone, activate account), account verification (e.g. reset password) user interfaces and user flows using dead-simple APIs.

This guide focuses on writing your own UI using Ory Kratos' APIs. If you are interested in just adding login and authentication to your app, check out Add Authentication to your Next.js / React Single Page Application (SPA)

Before we start, let's get some terminology out of the way:

  • At Ory, identity can mean any actor in a system (user, robot, service account, ...). The term user always refers to a human being sitting in front of a browser or mobile app.
  • A session refers to a user's session in a browser or mobile app after they have authenticated.
  • Self-Service refers to flows the user can do on their own - such as login, registration, and so on. It does not require administrative / support intervention.

Add Login to your React / NextJS

If you want to see a live demo right away, check out this app in action.

The code for this app is available on GitHub. To give it a spin, clone it and run the following commands:

git clone https://github.com/ory/kratos-selfservice-ui-react-nextjs.git
cd kratos-selfservice-ui-react-nextjs
npm i

To use your own Ory Kratos instance, you can use the ORY_SDK_URL environment variable. To get started we recommend to run Ory Kratos in an Ory Cloud Project, which is free for developers. You can create a new project on console.ory.sh or you via the Ory CLI. Install the CLI with the package manager of your choice on Linux, macOs, or Windows.

Create a new developer project with just two commands:

# Download the Ory CLI to your local directory:
bash <(curl https://raw.githubusercontent.com/ory/meta/master/install.sh) -b . ory
# install Ory CLI using cURl
./ory auth
# Log into an existing account or create a new one
./ory create project --name <your-project-name>
# Create a new project

After the project has been created the CLI displays the project details:

Project created successfully!
ID            a0c23a9d-bd3b-4a20-a6c0-00a1ada73f49
SLUG	        laughing-ardinghelli-cvaggbj1hi
STATE	        running
NAME	        Example

Copy the SLUG, and set the ORY_SDK_URL to the SDK URL of the project you just created:

# If you run Ory Kratos in Ory Cloud:
export ORY_SDK_URL=https://YOUR_PROJECT_SLUG_HERE.projects.oryapis.com

# Start the app
npm run dev

Next head over to http://localhost:3000/ to see the app in action with login, registration - a working user management!

Ory Kratos on your Machine

You can also run Ory Kratos on your own machine and develop in a local environment. A quick way to begin is to run the Ory Kratos Docker quickstart as it includes all the necessary dependencies. You can run Ory Kratos without Docker as well!

git clone --depth 1 --branch master https://github.com/ory/kratos.git
cd kratos
git checkout master
git pull -ff
docker-compose -f quickstart.yml -f contrib/quickstart/kratos/cloud/quickstart.yml up --build --force-recreate -d

In that case, set the ORY_SDK_URL to your local Ory Kratos instance:

# If you run Ory Kratos locally using the Docker quick start:
export ORY_KRATOS_URL=http://localhost:4455/

# Start the app
npm run dev

Ory Kratos Configuration in Ory Cloud

To get everything to work smoothly, we recommend setting the appropriate UI endpoints in your Ory Cloud Project under the "User Interface" menu item. If you are developing locally on port 3000 this would be:

  • Login UI: http://localhost:3000/login
  • Registration UI: http://localhost:3000/registration
  • Settings UI: http://localhost:3000/settings
  • Verification UI: http://localhost:3000/verification
  • Recovery UI: http://localhost:3000/recovery
  • Error UI: http://localhost:3000/error

Ory Cloud Project User Interface Configuration

You can also configure this (like all other Ory configuration) directly in the CLI, for example for the registration UI. Just switch out the flow name to configure the other UIs:

./ory patch project <your-project-id> --replace '/services/identity/config/selfservice/flows/registration/ui_url="http://localhost:3000/registration"'

Also, ensure to set up your redirects correctly, so you end up at the right endpoint after you have signed up or signed in!

Ory Cloud Project User Interface Configuration

We are setting these values to ensure that all flows (e.g. clicking on that password reset link) end up at your application. If you deploy to production, set these values to your production URL!

Start with the Next.js Typescript Template

To start from scratch, initialize the NextJS App and install Ory's SDKs and integration packages:

npx create-next-app --ts
npm i --save @ory/kratos-client @ory/integrations

To make the UI beautiful, we also install Ory's theme package. You can of course use your own styling framework (e.g. Material UI or Tailwind).

npm i --save @ory/themes

We also want to send notifications to users in case something goes wrong. For that, we will install React Toastify:

npm install --save react-toastify

Adding Next.js Edge Function to Integrate with Ory Kratos

To make everything run smoothly, we will add Ory's integration library and include it in Next.js Edge Runtime. To do so, add a new file under pages/api/.ory/[...paths].ts with the following contents:

Setting up the SDK to interact with Ory Cloud's APIs is just a few lines of code:

Rendering the Registration Form

Great, now all the preconditions are met! Let's start with the first page we want to implement: the registration form!

Preparing the Registration Page

First we need to initialize the state and get the Self-Service Registration Flow ID from the URL:

Initializing or Fetching a Registration Flow

Next, we create an effect which will fetch the registration flow and set the state. The registration flow contains information about the registration form, e.g. the fields and validation messages to be displayed:

As you can see, if the flow ID is not available, we will initialize a new registration flow (initializeSelfServiceRegistrationFlowForBrowsers). If it is set, we will fetch the flow from the API (getSelfServiceRegistrationFlow).

Preparing Registration Form Submission

When the user submits the form, we will call the submitSelfServiceRegistrationFlow method of the SDK to submit the form:

Rendering the Registration Form

Finally, we render the registration form:

Rendering the Forms

Great, we have now initialized the registration flow and have everything prepared to render the form. Rendering the form is the same for all flows (login, registration, recovery, ...). The <Flow onSubmit={onSubmit} flow={flow} /> React Component will render the form and handle the form state. The component itself is a bit longer because we deal with the form state, errors, and the form submission without any helper tools such as Formik. In essence, it iterates over the Registration Form's ui.node values which we received from initializeSelfServiceRegistrationFlowForBrowsers / getSelfServiceRegistrationFlow earlier:

Then, for each node, it decides what HTML input to render:

The simplest HTML input to render is the hidden input field. Basically you just add the attributes to the HTML element:

Rendering a normal input field looks similar:

Ory Kratos' forms can contain several types of nodes:

These are needed to show, for example, QR codes for TOTP, scripts for WebAuthn, text for recovery codes, buttons for social sign in, and so on!

Dealing With Flow Errors

Usually, Ory Kratos takes care of redirecting to the correct endpoints and showing the right messages. With Single Page Apps though you need to deal with errors yourself. Ory Kratos conveniently returns error IDs which you can use to identify errors and handle accordingly:

Rendering the Recovery Page

Rendering the recovery form is the same as the registration form, but with a few minor changes:

Rendering the Verification Page

Rendering the verification form is the same as the registration form, but with a few minor changes:

Rendering the Account Settings Page

Rendering the account settings form is the same as the registration form, but with a few minor changes:

Rendering the Login Page

The login page is a bit more work to render! That is because we want to support two-step authentication and we need to deal with any two-factor authentication errors by e.g. logging the user out.

Form Rendering Conclusion

That was quite a bit of code, but it's all there is to it! If you do not want to implement these UI screens yourself, use the reference implementations for Ory Kratos instead, or clone this repository and use it as a base for your project!

git clone https://github.com/ory/kratos-selfservice-ui-react-nextjs.git

Deploy to Vercel

The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js. If you have never deployed on Vercel, check out the Next.js deployment documentation for more details. Deploying the app is easy. Ensure that your build works by running

npm run build

Then, set up your Vercel account and create a new app. You will need to configure your Ory Cloud Project SDK URL or the URL of your self-hosted Ory Kratos instance in your Vercel deployment:

Add Ory Cloud SDK URL to Vercel

By the way! If you want to use separate Ory Kratos deployments for staging, production, and development then use different SDK URLs for the different environments by un/selecting the checkboxes in the Vercel UI:

Use a development project for development Vercel

Use a production project for production Vercel

If you want to call Ory Cloud's Admin APIs from your Next.js Edge serverless functions, optionally set up the Ory Personal Access Token:

Connect Vercel with Ory Personal Access Token

Next all you need to do is to run the deploy command and connect it to the project you created:

npx vercel deploy --prod

This also works with Vercel PR Preview!

End-to-End Tests

Adding end-to-end tests is also easy! Clone the repository and run the following commands:

git clone https://github.com/ory/kratos-selfservice-ui-react-nextjs.git
cd kratos-selfservice-ui-react-nextjs
npm i

Then, depending on your setup, you can either use Ory Kratos local or in Ory Cloud:

export ORY_KRATOS_URL=https://playground.projects.oryapis.com/

Then, build and start the server

npm run dev

and in a new shell run the end-to-end tests:

npm run test:dev

You can find the full spec file in the cypress/integration/pages.spec.js file:

The GitHub Action file is also straight forward and contains two configurations, one for running Ory Kratos locally and one for running Ory Kratos in Ory Cloud:

Conclusion

Adding login and registration to your Next.js app is a breeze with open source technology like Ory Kratos and Next.js.

We hope you enjoyed this guide and found it helpful! If you have any questions, check out the Ory community on Slack and GitHub!