How To Integrate Passkeys in Next.js Apps (TypeScript)
Tags: authentication, passkeys, webdev, nextjs
Published: 2023-07-12 09:29:04

## 1\. Introduction
The final result of this tutorial looks as follows:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3brlqlmj3d1kttbk7r8t.png)

## 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 [here](https://www.corbado.com/blog/nextjs-passkeys)):

{% embed https://gist.github.com/vincentdelitz/121eaec3048e8df7d163e4112917003f.js %}

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](https://github.com/corbado/example-passkeys-nextjs).

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](https://app.corbado.com/signin) to sign up and create your account (you'll see the passkey sign-up in action here!).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1zi1tx0hvcuh7jozbt7.png)

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](https://app.corbado.com/app/getting-started/integration-guide) that helps to set up all required settings.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tck0hfyaqdqwpkhze4x4.png)

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").

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uqpx4rpw5793z86x3983.png)

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60373yqa6a7ncdj2y7ab.png)

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.

{% embed https://gist.github.com/vincentdelitz/699b67897aa9fb6fdcee1e1e5ea8c81c.js %}

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):

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3imhz3ijhvw10wu388ot.png)

-   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 the 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):

{% embed https://gist.github.com/vincentdelitz/c5bb91a0778996bbefe45c3e2b0c3d6d.js %}

Optionally, you can modify the styling (via [CSS classes](https://docs.corbado.com/integrations/web-component#2.-adapt-styling-optional)) and text / behavior (via the [developer panel](https://app.corbado.com/app/settings/userinterface) or via [HTML attributes](https://docs.corbado.com/integrations/web-component#1.-embed-the-web-component-into-your-site)).

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):

{% embed https://gist.github.com/vincentdelitz/0003d179266c39d8882b584483b9c0e4.js %}

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:

{% embed https://gist.github.com/vincentdelitz/a8b767363d1a1d401ae76af0a03636a2.js %}

### 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.

{% embed https://gist.github.com/vincentdelitz/a296bf8ec3a5af089f54342992b8744c.js %}

### 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).

{% embed https://gist.github.com/vincentdelitz/7a400ad51e11be4ed160f952245ad7e1.js %}

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:

{% embed https://gist.github.com/vincentdelitz/40b3c74133fa2c1e06982f72840a9218.js %}


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

{% embed https://gist.github.com/vincentdelitz/e42ba64b9be204f7bb2ff08d33925976.js %}

### 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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktd28a6fy021riet3cvy.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gqvnt5eid6q00660f7cf.png)

## 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 [here](https://docs.corbado.com/sessions/session-data/getting-data/getting-data-from-corbado-backend)or if you want to add Corbado to your existing app with existing users, please see [here](https://docs.corbado.com/integrations/web-component/existing-application-with-existing-users).