Edit

Share via


Implement passkeys in ASP.NET Core Blazor Web Apps

This guide explains how to implement passkey support for a new or existing Blazor Web App with ASP.NET Core Identity.

For an overview of passkeys and general configuration guidance, see Enable Web Authentication API (WebAuthn) passkeys.

Prerequisites

.NET 10 SDK

Create a Blazor Web App

Use the following guidance to create a new Blazor Web App with ASP.NET Core Identity, which includes passkeys support.

Note

Visual Studio 2022 or later and .NET 10 or later SDK are required.

In Visual Studio:

  • Select Create a new project from the Start Window or select File > New > Project from the menu bar.
  • In the Create a new project dialog, select Blazor Web App from the list of project templates. Select the Next button.
  • In the Configure your new project dialog, name the project BlazorWebAppPasskeys in the Project name field, including matching the capitalization. Using this exact project name is important to ensure that the namespaces match for code that you copy from the article into the app that you're building.
  • Confirm that the Location for the app is suitable. Leave the Place solution and project in the same directory checkbox selected. Select the Next button.
  • In the Additional information dialog, set the Authentication type to Individual Accounts. Use the following settings for the other options:
    • Framework: Latest framework release (.NET 10 or later)
    • Configure for HTTPS: Selected
    • Interactive render mode: Server
    • Interactivity location: Global
    • Include sample pages: Selected
    • Do not use top-level statements: Not selected
    • Use the .dev.localhost TLD in the application URL: Not selected
    • Select Create.

The preceding instructions create a Blazor Web App with:

  • ASP.NET Core Identity configured for user authentication using the -au|--authentication option.
  • Entity Framework Core with SQLite for data storage.
  • Passkey registration and authentication endpoints.
  • UI components for managing passkeys.

Note

Currently, only the Blazor Web App project template includes built-in passkey support.

Run the application

Press F5 to run the app with debugging or Ctrl+F5 to run the app without debugging.

The following guidance relies upon an app that was created with Individual Accounts for the app's Authentication type or scaffolding Identity into an existing app.

Prerequisites

  • An existing Blazor Web App (.NET 10 or later) with ASP.NET Core Identity
  • .NET 10 SDK

For migration guidance, see Migrate an ASP.NET Core app.

Reference source guidance

The links in this article to .NET reference source load the repository's default branch, which represents the current development for the next release of .NET. To select a tag for a specific release, use the Switch branches or tags dropdown list. For more information, see How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205).

Update Identity schema version

In Program.cs, update the Identity configuration to use schema version 3, which includes passkey support:

builder.Services.AddIdentityCore<ApplicationUser>(options =>
{
    options.SignIn.RequireConfirmedAccount = true;
    options.Stores.SchemaVersion = IdentitySchemaVersions.Version3;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders();

Create and run a database migration

In Visual Studio Solution Explorer, double-click Connected Services. In the Service Dependencies area, select the ellipsis (...) followed by Add migration in the SQL Server Express LocalDB area.

Give the migration a Migration name of AddPasskeySupport to describe the migration. Wait for the database context to load in the DbContext class names field. Select Finish to create the migration. Select the Close button when the operation completes.

Select the ellipsis (...) again followed by the Update database command.

The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load. Select the Finish button. Select the Close button when the operation completes.

Create passkey model classes

Add the following model classes to the project in the Components/Account folder with BlazorWebCSharp._1.Components.Account namespace updates for the app (for example: Contoso.Components.Account):

Create the PasskeySubmit component

Add the following PasskeySubmit component to handle passkey operations:

Components/Account/Shared/PasskeySubmit.razor

Add the JavaScript for passkey operations

Add the following JavaScript file to handle WebAuthn API interactions:

Components/Account/Shared/PasskeySubmit.razor.js

Add passkey endpoints

Update the IdentityComponentsEndpointRouteBuilderExtensions.cs file (or create the file if it doesn't exist and call MapAdditionalIdentityEndpoints in the Program file) to include the passkey-specific endpoints:

/PasskeyCreationOptions and /PasskeyRequestOptions endpoints

Update the Login page

Replace the existing Login component with the following component and update the BlazorWebCSharp._1.Data namespace to match the app (for example: Contoso.Components.Account.Data):

Components/Account/Pages/Login.razor

Add a redirect method to the IdentityRedirectManager class

Add the following method to the IdentityRedirectManager class in Components/Account/IdentityRedirectManager.cs:

public void RedirectToInvalidUser(
    UserManager<ApplicationUser> userManager, HttpContext context) =>
        RedirectToWithStatus("Account/InvalidUser",
            $"Error: Unable to load user with ID '{userManager.GetUserId(context.User)}'.",
            context);

Create passkey management pages for adding and renaming passkeys

Add the following Passkeys component for managing passkeys and update the BlazorWebCSharp._1.Data namespace to match the app (for example: Contoso.Components.Account.Data):

Components/Account/Pages/Manage/Passkeys.razor

Add the following RenamePasskey component for renaming passkeys and update the BlazorWebCSharp._1.Data namespace to match the app (for example: Contoso.Components.Account.Data):

Components/Account/Pages/Manage/RenamePasskey.razor

Update the manage navigation menu

Add a link to the passkey management page in the app's ManageNavMenu component.

In Components/Account/Shared/ManageNavMenu.razor, add the following NavLink component for the Passkeys component:

<li class="nav-item">
    <NavLink class="nav-link" href="Account/Manage/Passkeys">Passkeys</NavLink>
</li>

Include the JavaScript file

In the App component (Components/App.razor), locate the Blazor script tag:

<script src="_framework/blazor.web.js"></script>

Immediately after the Blazor script tag, add a reference to the PasskeySubmit JavaScript module:

<script src="Components/Account/Shared/PasskeySubmit.razor.js" type="module"></script>

Register a passkey

To test passkey functionality:

  1. Register a new account or sign in with an existing account.
  2. Navigate to Manage your account (select the username in the navigation menu).
  3. Select Passkeys from the navigation menu.
  4. Select Add a new passkey
  5. Follow the browser's prompts to create a passkey using your device's authenticator.

Sign in with a passkey

After a passkey is registered:

  1. Sign out of the app.
  2. On the login page, enter your email address.
  3. Select Log in with a passkey.
  4. Follow the browser's prompts to authenticate with your passkey.
  5. Navigate to Account/Manage/Passkeys to add, rename, or delete passkeys.
  6. If the passkey supports passkey autofill (conditional UI) for login, test the passkey autofill feature by selecting the email input field when you have saved passkeys.

Mitigate PublicKeyCredential.toJSON error (TypeError: Illegal invocation)

Some password managers don't implement the PublicKeyCredential.toJSON method correctly, which is required for JSON.stringify to work when serializing passkey credentials. When registering or authenticating a user with an app based on the Blazor Web App project template, the following error is thrown when attempting to add a passkey:

Error: Could not add a passkey: Illegal invocation

For guidance on mitigating this error, see Enable Web Authentication API (WebAuthn) passkeys.

Additional resources