Building a Next.js Passkey Login Page with TypeScript

Building a Next.js Passkey Login Page with TypeScript

In this blog post, we’ll be walking through the process of building a sample application with passkey authentication using Next.js and TypeScript. We’ll cover how to embed the Corbado web component and implement passkey login functionality for a seamless user experience.

1. Introduction

2. Prerequisites

3. Set up the Next.js project

4. Repository structure

5. Set up the Corbado web component for passkey authentication

      5.1 Set up your Corbado account and project

      5.2 Embed the web component in your frontend

      5.3 Set up the profile page

      5.4 Add Corbado session management

      5.5 Run the application

6. Conclusion

1. Introduction

The final result of this tutorial looks as follows:

2. Prerequisites

This tutorial assumes basic familiarity with Next.js, HTML, CSS and JavaScript / TypeScript. Let’s dive in! Moreover, you need to have Node and NPM installed on your machine.

3. Repository structure

Let’s first discuss the structure of our project (full GitHub repo):

The rest of the files of this project can be ignored for the purpose of this tutorial.

4. Set up the Next.js project

In the following, we explain step-by-step what needs to be done to successfully set up the Next.js project. If you want to see the finished code, please have a look at our sample application repository.

Let’s start out by initializing a new Next.js project:

npx create-next-app@latest

In the installation guide steps, we select the following:

  • Project name: passkeys-demo-nextjs
  • TypeScript: Yes
  • ESLint: Yes
  • Tailwind CSS: No
  • src/ directory: Yes
  • App Router: Yes
  • Default import alias: No

5. Set up the Corbado web component for passkey authentication

5.1 Set up your Corbado account and project

Visit the Corbado developer panel to sign up and create your account (you'll see the passkey sign-up in action here!).

In the appearing project wizard, select “Integration guide”, “Web component” as integration mode and “No existing users” as we’re building a new app from scratch.

Then, jump over to the integration guide that helps to set up all required settings.

At first, we need to define a new authorized origin, which is in the case of our Next.js application "http://localhost:3000" (you can give it any name you want, e.g. "local").

Create an API secret which is needed to later request user data from the Corbado backend.

Navigate to the root directory of the project:

cd passkeys-demo-nextjs

Create a new .env file at the root of your project. Copy and paste the API secret as well as the project ID above into it. Note, that in this tutorial, we don't necessarily need the API secret as we're not making any requests from a backend to Corbado. For the sake of completeness and easier future adaption, we add the API secret here already though.

Next.js enables the straightforward use of environment variables through process.env.ENV_VARIABLE_NAME. Those variables prefixed with NEXT_PUBLIC_ can be accessed in both client-side and server-side routes, as Next.js automatically embeds these into the JavaScript bundle during the build process.

On the other hand, environment variables without this prefix are treated as secret and can only be accessed in server-side routes. This is because Next.js does not expose these variables to the client-side to ensure the confidentiality of potentially sensitive information.

In the case of our tutorial’s example application, we will only be making use of client-side routes, hence we will primarily work with variables that have the NEXT_PUBLIC prefix.

Remember, sensitive information such as database credentials, API keys, etc., should not be prefixed with NEXT_PUBLIC_ to avoid accidental exposure to the client-side. Next, we set the Application URL, Redirect URL and Relying Party ID to the following values (see explanation below):

  • Application URL: Provide the URL where you embedded the web component, here: http://localhost:3000
  • Redirect URL: Provide the URL your app should redirect to after successful authentication and which gets sent a short-term session cookie, here: http://localhost:3000/profile
  • Relying Party ID: Provide the domain (no protocol, no port and no path) where passkeys should be bound to, here: localhost

The last two steps in the integration guide (“Add Corbado session management and protect your routes” and “Start using passkeys”) will be covered below.

5.2 Embed the web component in your frontend

First of all, we need to install the web component:

npm i @corbado/webcomponent

Then, we remove the default content from our homepage (src/app/page.tsx) and add the web component CSS import. Moreover, we include the <corbado-auth/> web component. As HTML attribute “project-id”, we take the environment variable for project ID (NEXT_PUBLIC_PROJECT_ID):

Optionally, you can modify the styling (via CSS classes) and text / behavior (via the developer panel or via HTML attributes).

As Next.js uses server-side-rendering (SSR), we need a workaround to run the web component only on client-side. Use the following code to make the web component available in Next.js (src/app/page.tsx):

In the same file, add the import for useEffect (import {useEffect} from 'react';) and add ‘use client’; in the first line.

To improve the styling, we remove all the default code from src/app/globals.css.

Moreover, to ensure that the ESlinter works properly create a .d.ts file in the src folder, e.g. “declarations.d.ts”, and add the following code:

5.3 Set up the profile page

After successful authentication, the Corbado web component redirects the user to the provided Redirect URL (https://localhost:3000/profile). Therefore, we create a new folder “src/pages” and add a file profile.tsx in it. This file renders basic user information (user ID and email) and provides a button to logout.

5.4 Add Corbado session management

On every frontend page, where we want to add protected content or resources, we need to add the Corbado session management logic. This is required to make the session refresh work as expected. Add / modify the following code in src/pages/profile.tsx page (add the imports for useEffect and useState from ‘react’ if necessary on top of the file).

To provide more context, we add user profile information to the profile page if the user is successfully authenticated and add a logout button. This requires also introducing a User type for TypeScript. For a better user expierence when the application is authenticating / loading, we add a loading spinner. Here, we use react-loader-spinner, but any other spinner can be used of course as well. To make the loading spinner appear at the right times, we also introduce the variable "loading".

Install the react-loader-spinner via NPM:

npm i react-loader-spinner

We decided to use the <LineWave/> loading spinner in this tutorial. The full src/pages/profile.tsx page now looks as follows:

The full src/app/page.tsx page now looks as follows:

5.5 Run the application

If everything is set up and installed, run the application with

npm run dev

You should see the following screen:

After successful sign up / login, you see the profile page:

6. Conclusion

This tutorial showed how easy it is to add passwordless authentication with passkeys to a Next.js app using Corbado. Besides the passkey-first authentication, Corbado provides simple session management, that we used for a retrieval of basic user data. If you want to read more about how you can leverage the session management to retrieve backend data, please see Corbado docs or if you want to add Corbado to your existing app with existing users, please see Corbado docs.

Enjoyed this read?

Stay up to date with the latest news, strategies and insights about passkeys sent straight to your inbox!