In this blog post, we'll be walking through the process of building a sample
application with passkey authentication using Next.js as a web framework and NextAuth.js as authentication library. To make
passkeys work, we plug Corbados Passkey Associate web component into the NextAuth.js authentication
process. It automatically connects to a passkeys backend and handles all
passkeys related aspects of authentication (e.g. generating and verifying the
WebAuthn challenge, handling Conditional UI, etc).
This tutorial assumes basic familiarity with Next.js, NextAuth.js, TypeScript
and HTML. Lets dive in!
3. Repository
structure for NextAuth.js passkey project
Our Next.js project with integrated NextAuth.js
authentication is structured like this.
Note that these are only the most important files.
├── pages
| ├── api
| | ...
| | └── auth
| | ├── [...nextauth].ts # Configuration of the authentication providers
| | └── associate.ts # Endpoint which requests an association token from Corbado
| |
| ├── auth
| | ├── redirect.tsx # Page where the user gets redirected to by Corbado after authentication
| | └── signin.tsx # Sign in page which also contains the Corbado web component
| |
| └── index.tsx # Main page which is shown when no path is given
|
├── .env.local # Contains the environment variables
We use a concept called Passkey Association where an already authenticated user (e.g. via OAuth,
password or any other conventional method) can add a passkey to their account
and subsequently login with this passkey. This means that a user cannot
directly register using a passkey, but the user can add a passkey once they
have created an account.
Creating a passkey account and using it to log into your app will work as
shown here:
The diagram show the following processes:
Creating a passkey (1-4):
The application requests an association token for a certain authenticated
user from our backend
Our backend requests this association token from Corbado's backend
Corbado's backend returns the token to our backend
Our backend returns the token to our frontend and the frontend hands it to
the web component which will then display a
Create passkey button
This enables the user to create a passkey which they can then use to login as
follows:
Login with a passkey (5-9):
After the user has entered his email into the corbado-passkey-associate-
login webcomponent, the webcomponent gets a challenge from Corbado's backend
The webcomponent sends back the challenge response to the Corbado backend
If the authentication was successful the user is redirected to the
redirectURL (You can configure it in the developer panel), if the
authentication was unsuccessful you get a notification so you can display an
error
In the redirectPage we tell NextAuth that someone has logged in with a
passkey
We obtain the current user from Corbado's session and hand it to NextAuth
which will initiate a session itself for that user and proceed as normal
You can read more about the Passkey Associate concept in our
docs.
4. Set up your Corbado
account and project
Visit the Corbado developer panel to sign up and
create your account (youll see passkey sign-up in action here!).
In the appearing project wizard, select Web app as type of app and
afterward select whether you have existing users or not (which does not matter
to us in this case because only existing, authenticated users can add a
passkey). Moreover, providing some details regarding your frontend and backend
tech stack as well as the main goal you want to achieve with Corbado helps us
to customize and smoothen your developer experience.
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/auth/redirect
Relying Party ID: Provide the domain (no protocol, no port and no path) where passkeys should be bound to, here: localhost
5. Set up Next.js with
NextAuth.js
We download the NextAuth.js example from
here and run
The default page should appear:
When we click on Sign in, we are redirected to the NextAuth.js default
authentication page.
For demo purposes, we went to the Google developer console and generated credentials to be
able to use Google as an OAuth provider. The NextAuth.js
example reads the OAuth credentials for all providers from the environment, so
we create a .env.local file and place our Google credentials there.
Afterwards, we can sign in using our Google account!
Our initial project is now set up. Lets add passkey authentication!
6. Create passkey login page
6.1 Create custom
login page for NextAuth.js providers
Apart from email magic links and OAuth providers, the UI of the NextAuth.js
default authentication page only supports custom inputs in the form of text
fields as a separate way of authentication. We, however, want to use passkeys,
which cannot be used via text fields. Therefore, we create our own login page
under /pages/auth/signin.tsx with some bootstrapping:
To clarify: We only create the UI ourselves. The authentication is still
handled by NextAuth.js and gets initiated when we call the signIn method that
NextAuth.js provides.
6.2 Embed the passkey
authentication webcomponent
We now add the to our signIn page.
Notice how we also filter out the webauthn authentication provider (our
CredentialsProvider).
6.3 Create redirect page
After successful authentication, the Corbado web component redirects the user
to the Redirect URL we configured in step 4 (/auth/redirect).
We create a file under /pages/auth/redirect.tsx and add the following code.
This just calls the signIn method of NextAuth.js, but with the
parameters credentials instead of an OAuth-provider-id.
6.4 Add credentials
provider for the custom passkey login
To be able to call NextAuth.jss signIn method with credentials
as parameter, we need to configure a custom authentication provider, so
NextAuth.js knows what to do and when to generate a session for which user.
The authentication providers for NextAuth.js are configured in
/pages/api/auth/[¦nextauth].ts.
Here, we add a CredentialsProvider to incorporate our custom authentication
option. The CredentialsProvider contains an authorize method which gets
called by NextAuth.js after we use the signIn method (step 6.3).
We obtain the current user from the session that Corbado has initiated. By
returning an object containing email and name, we tell NextAuth.js the current
user and NextAuth.js will therefore initialize a session itself, which will
then be used in all of your application pages.
7. Add passkey associate component
The web component will allow an authenticated
user to add a passkey to their account and afterwards login with it using the
web component we already integrated.
To get our association token, we create our own endpoint under
/pages/api/auth/association.ts which requests a token for a specific user from
the Corbado backend and returns it to us.
In our frontend, we use this endpoint to get the association token for our
current user and have the web component display
the Create Passkey button:
Thats it our app is fully set up and configured!
8. Start
using passkeys with our NextAuth.js implementation
Clicking on "Sign in" should redirect you to our custom signIn page:
Now login with Google or any other provider. After authentication, you will be
sent to the index page where you have the possibility to add a passkey to your
account:
Click on the Create passkey button and create a passkey.
Sign out and go to the "Sign in" page again. If you now enter the email of
the OAuth account into the Corbado web component, you should be able to log in
using the passkey you just created.
9. Conclusion
This tutorial showed how easy it is to add passwordless authentication with passkeys to
NextAuth.js using Corbado. We only used Corbado for passkey login, but Corbado
can also provide passkey sign-up together with passkey login and email links
as fallback. If you want to read more about Corbado as an all-in-one
authentication solution, please check out our documentation
here.
Table of Contents
Enjoyed this read?
🤝 Join our Passkeys Community
Share passkeys implementation tips and get support to free the world from passwords.