Secure an ASP.NET Core Blazor WebAssembly standalone app with the Authentication library

This article explains how to secure an ASP.NET Core Blazor WebAssembly standalone app with the Blazor WebAssembly Authentication library.

For Azure Active Directory (AAD) and Azure Active Directory B2C (AAD B2C), don't follow the guidance in this topic. See the AAD and AAD B2C topics in this table of contents node.

To create a standalone Blazor WebAssembly app that uses Microsoft.AspNetCore.Components.WebAssembly.Authentication library, follow the guidance for your choice of tooling. If adding support for authentication, see the following sections of this article for guidance on setting up and configuring the app.

Note

The Identity Provider (IP) must use OpenID Connect (OIDC). For example, Facebook's IP isn't an OIDC-compliant provider, so the guidance in this topic doesn't work with the Facebook IP. For more information, see Secure ASP.NET Core Blazor WebAssembly.

To create a new Blazor WebAssembly project with an authentication mechanism:

  1. After choosing the Blazor WebAssembly App template in the Create a new ASP.NET Core Web Application dialog, select Change under Authentication.

  2. Select Individual User Accounts to use ASP.NET Core's Identity system. This selection adds authentication support and doesn't result in storing users in a database. The following sections of this article provide further details.

Authentication package

When an app is created to use Individual User Accounts, the app automatically receives a package reference for the Microsoft.AspNetCore.Components.WebAssembly.Authentication package. The package provides a set of primitives that help the app authenticate users and obtain tokens to call protected APIs.

If adding authentication to an app, manually add the Microsoft.AspNetCore.Components.WebAssembly.Authentication package to the app.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Authentication service support

Support for authenticating users is registered in the service container with the AddOidcAuthentication extension method provided by the Microsoft.AspNetCore.Components.WebAssembly.Authentication package. This method sets up the services required for the app to interact with the Identity Provider (IP).

For a new app, provide values for the {AUTHORITY} and {CLIENT ID} placeholders in the following configuration. Provide other configuration values that are required for use with the app's IP. The example is for Google, which requires PostLogoutRedirectUri, RedirectUri, and ResponseType. If adding authentication to an app, manually add the following code and configuration to the app with values for the placeholders and other configuration values.

Program.cs:

builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("Local", options.ProviderOptions);
});

Configuration is supplied by the wwwroot/appsettings.json file:

{
  "Local": {
    "Authority": "{AUTHORITY}",
    "ClientId": "{CLIENT ID}"
  }
}

Google OAuth 2.0 OIDC example for an app that runs on the localhost address at port 5001:

{
  "Local": {
    "Authority": "https://accounts.google.com/",
    "ClientId": "2.......7-e.....................q.apps.googleusercontent.com",
    "PostLogoutRedirectUri": "https://localhost:5001/authentication/logout-callback",
    "RedirectUri": "https://localhost:5001/authentication/login-callback",
    "ResponseType": "id_token"
  }
}

The redirect URI (https://localhost:5001/authentication/login-callback) is registered in the Google APIs console in Credentials > {NAME} > Authorized redirect URIs, where {NAME} is the app's client name in the OAuth 2.0 Client IDs app list of the Google APIs console.

Authentication support for standalone apps is offered using OpenID Connect (OIDC). The AddOidcAuthentication method accepts a callback to configure the parameters required to authenticate an app using OIDC. The values required for configuring the app can be obtained from the OIDC-compliant IP. Obtain the values when you register the app, which typically occurs in their online portal.

Access token scopes

The Blazor WebAssembly template automatically configures default scopes for openid and profile.

The Blazor WebAssembly template doesn't automatically configure the app to request an access token for a secure API. To provision an access token as part of the sign-in flow, add the scope to the default token scopes of the OidcProviderOptions. If adding authentication to an app, manually add the following code and configure the scope URI.

Program.cs:

builder.Services.AddOidcAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultScopes.Add("{SCOPE URI}");
});

For more information, see the following sections of the Additional scenarios article:

Imports file

The Microsoft.AspNetCore.Components.Authorization namespace is made available throughout the app via the _Imports.razor file:

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared

Index page

The Index page (wwwroot/index.html) page includes a script that defines the AuthenticationService in JavaScript. AuthenticationService handles the low-level details of the OIDC protocol. The app internally calls methods defined in the script to perform the authentication operations.

<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>

App component

The App component (App.razor) is similar to the App component found in Blazor Server apps:

  • The CascadingAuthenticationState component manages exposing the AuthenticationState to the rest of the app.
  • The AuthorizeRouteView component makes sure that the current user is authorized to access a given page or otherwise renders the RedirectToLogin component.
  • The RedirectToLogin component manages redirecting unauthorized users to the login page.

Due to changes in the framework across releases of ASP.NET Core, Razor markup for the App component (App.razor) isn't shown in this section. To inspect the markup of the component for a given release, use either of the following approaches:

  • Create an app provisioned for authentication from the default Blazor WebAssembly project template for the version of ASP.NET Core that you intend to use. Inspect the App component (App.razor) in the generated app.

  • Inspect the App component (App.razor) in reference source.

    Note

    Documentation links to .NET reference source usually 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).

RedirectToLogin component

The RedirectToLogin component (Shared/RedirectToLogin.razor):

  • Manages redirecting unauthorized users to the login page.
  • Preserves the current URL that the user is attempting to access so that they can be returned to that page if authentication is successful.
@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Options

@inject IOptionsSnapshot<RemoteAuthenticationOptions<ApiAuthorizationProviderOptions>> Options
@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateToLogin(Options.Get(
            Microsoft.Extensions.Options.Options.DefaultName)
            .AuthenticationPaths.LogInPath);
    }
}

LoginDisplay component

The LoginDisplay component (Shared/LoginDisplay.razor) is rendered in the MainLayout component (Shared/MainLayout.razor) and manages the following behaviors:

  • For authenticated users:
    • Displays the current username.
    • Offers a button to log out of the app.
  • For anonymous users, offers the option to log in.

Due to changes in the framework across releases of ASP.NET Core, Razor markup for the LoginDisplay component isn't shown in this section. To inspect the markup of the component for a given release, use either of the following approaches:

  • Create an app provisioned for authentication from the default Blazor WebAssembly project template for the version of ASP.NET Core that you intend to use. Inspect the LoginDisplay component in the generated app.

  • Inspect the LoginDisplay component in reference source.

    Note

    Documentation links to .NET reference source usually 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).

Authentication component

The page produced by the Authentication component (Pages/Authentication.razor) defines the routes required for handling different authentication stages.

The RemoteAuthenticatorView component:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string Action { get; set; }
}

Troubleshoot

Logging

To enable debug or trace logging for Blazor WebAssembly authentication, see ASP.NET Core Blazor logging.

Common errors

  • Misconfiguration of the app or Identity Provider (IP)

    The most common errors are caused by incorrect configuration. The following are a few examples:

    • Depending on the requirements of the scenario, a missing or incorrect Authority, Instance, Tenant ID, Tenant domain, Client ID, or Redirect URI prevents an app from authenticating clients.
    • An incorrect access token scope prevents clients from accessing server web API endpoints.
    • Incorrect or missing server API permissions prevent clients from accessing server web API endpoints.
    • Running the app at a different port than is configured in the Redirect URI of the Identity Provider's app registration.

    Configuration sections of this article's guidance show examples of the correct configuration. Carefully check each section of the article looking for app and IP misconfiguration.

    If the configuration appears correct:

    • Analyze application logs.

    • Examine the network traffic between the client app and the IP or server app with the browser's developer tools. Often, an exact error message or a message with a clue to what's causing the problem is returned to the client by the IP or server app after making a request. Developer tools guidance is found in the following articles:

    • Decode the contents of a JSON Web Token (JWT) used for authenticating a client or accessing a server web API, depending on where the problem is occurring. For more information, see Inspect the content of a JSON Web Token (JWT).

    The documentation team responds to document feedback and bugs in articles (open an issue from the This page feedback section) but is unable to provide product support. Several public support forums are available to assist with troubleshooting an app. We recommend the following:

    The preceding forums are not owned or controlled by Microsoft.

    For non-security, non-sensitive, and non-confidential reproducible framework bug reports, open an issue with the ASP.NET Core product unit. Don't open an issue with the product unit until you've thoroughly investigated the cause of a problem and can't resolve it on your own and with the help of the community on a public support forum. The product unit isn't able to troubleshoot individual apps that are broken due to simple misconfiguration or use cases involving third-party services. If a report is sensitive or confidential in nature or describes a potential security flaw in the product that attackers may exploit, see Reporting security issues and bugs (dotnet/aspnetcore GitHub repository).

  • Unauthorized client for AAD

    info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.

    Login callback error from AAD:

    • Error: unauthorized_client
    • Description: AADB2C90058: The provided application is not configured to allow public clients.

    To resolve the error:

    1. In the Azure portal, access the app's manifest.
    2. Set the allowPublicClient attribute to null or true.

Cookies and site data

Cookies and site data can persist across app updates and interfere with testing and troubleshooting. Clear the following when making app code changes, user account changes with the provider, or provider app configuration changes:

  • User sign-in cookies
  • App cookies
  • Cached and stored site data

One approach to prevent lingering cookies and site data from interfering with testing and troubleshooting is to:

  • Configure a browser
    • Use a browser for testing that you can configure to delete all cookie and site data each time the browser is closed.
    • Make sure that the browser is closed manually or by the IDE for any change to the app, test user, or provider configuration.
  • Use a custom command to open a browser in incognito or private mode in Visual Studio:
    • Open Browse With dialog box from Visual Studio's Run button.
    • Select the Add button.
    • Provide the path to your browser in the Program field. The following executable paths are typical installation locations for Windows 10. If your browser is installed in a different location or you aren't using Windows 10, provide the path to the browser's executable.
      • Microsoft Edge: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
      • Google Chrome: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      • Mozilla Firefox: C:\Program Files\Mozilla Firefox\firefox.exe
    • In the Arguments field, provide the command-line option that the browser uses to open in incognito or private mode. Some browsers require the URL of the app.
      • Microsoft Edge: Use -inprivate.
      • Google Chrome: Use --incognito --new-window {URL}, where the placeholder {URL} is the URL to open (for example, https://localhost:5001).
      • Mozilla Firefox: Use -private -url {URL}, where the placeholder {URL} is the URL to open (for example, https://localhost:5001).
    • Provide a name in the Friendly name field. For example, Firefox Auth Testing.
    • Select the OK button.
    • To avoid having to select the browser profile for each iteration of testing with an app, set the profile as the default with the Set as Default button.
    • Make sure that the browser is closed by the IDE for any change to the app, test user, or provider configuration.

App upgrades

A functioning app may fail immediately after upgrading either the .NET Core SDK on the development machine or changing package versions within the app. In some cases, incoherent packages may break an app when performing major upgrades. Most of these issues can be fixed by following these instructions:

  1. Clear the local system's NuGet package caches by executing dotnet nuget locals all --clear from a command shell.
  2. Delete the project's bin and obj folders.
  3. Restore and rebuild the project.
  4. Delete all of the files in the deployment folder on the server prior to redeploying the app.

Note

Use of package versions incompatible with the app's target framework isn't supported. For information on a package, use the NuGet Gallery or FuGet Package Explorer.

Run the Server app

When testing and troubleshooting a hosted Blazor WebAssembly solution, make sure that you're running the app from the Server project. For example in Visual Studio, confirm that the Server project is highlighted in Solution Explorer before you start the app with any of the following approaches:

  • Select the Run button.
  • Use Debug > Start Debugging from the menu.
  • Press F5.

Inspect the user

The ASP.NET Core framework's test assets include a Blazor WebAssembly client app with a User component that can be useful in troubleshooting. The User component can be used directly in apps or serve as the basis for further customization:

User test component in the dotnet/aspnetcore GitHub repository

Note

Documentation links to .NET reference source usually 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).

Inspect the content of a JSON Web Token (JWT)

To decode a JSON Web Token (JWT), use Microsoft's jwt.ms tool. Values in the UI never leave your browser.

Example encoded JWT (shortened for display):

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q

Example JWT decoded by the tool for an app that authenticates against Azure AAD B2C:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
  "exp": 1610059429,
  "nbf": 1610055829,
  "ver": "1.0",
  "iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
  "sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
  "aud": "70bde375-fce3-4b82-984a-b247d823a03f",
  "nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
  "iat": 1610055829,
  "auth_time": 1610055822,
  "idp": "idp.com",
  "tfp": "B2C_1_signupsignin"
}.[Signature]

Additional resources

For Azure Active Directory (AAD) and Azure Active Directory B2C (AAD B2C), don't follow the guidance in this topic. See the AAD and AAD B2C topics in this table of contents node.

To create a standalone Blazor WebAssembly app that uses Microsoft.AspNetCore.Components.WebAssembly.Authentication library, follow the guidance for your choice of tooling. If adding support for authentication, see the following sections of this article for guidance on setting up and configuring the app.

Note

The Identity Provider (IP) must use OpenID Connect (OIDC). For example, Facebook's IP isn't an OIDC-compliant provider, so the guidance in this topic doesn't work with the Facebook IP. For more information, see Secure ASP.NET Core Blazor WebAssembly.

To create a new Blazor WebAssembly project with an authentication mechanism:

  1. After choosing the Blazor WebAssembly App template in the Create a new ASP.NET Core Web Application dialog, select Change under Authentication.

  2. Select Individual User Accounts to use ASP.NET Core's Identity system. This selection adds authentication support and doesn't result in storing users in a database. The following sections of this article provide further details.

Authentication package

When an app is created to use Individual User Accounts, the app automatically receives a package reference for the Microsoft.AspNetCore.Components.WebAssembly.Authentication package. The package provides a set of primitives that help the app authenticate users and obtain tokens to call protected APIs.

If adding authentication to an app, manually add the Microsoft.AspNetCore.Components.WebAssembly.Authentication package to the app.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Authentication service support

Support for authenticating users is registered in the service container with the AddOidcAuthentication extension method provided by the Microsoft.AspNetCore.Components.WebAssembly.Authentication package. This method sets up the services required for the app to interact with the Identity Provider (IP).

For a new app, provide values for the {AUTHORITY} and {CLIENT ID} placeholders in the following configuration. Provide other configuration values that are required for use with the app's IP. The example is for Google, which requires PostLogoutRedirectUri, RedirectUri, and ResponseType. If adding authentication to an app, manually add the following code and configuration to the app with values for the placeholders and other configuration values.

Program.cs:

builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("Local", options.ProviderOptions);
});

Configuration is supplied by the wwwroot/appsettings.json file:

{
  "Local": {
    "Authority": "{AUTHORITY}",
    "ClientId": "{CLIENT ID}"
  }
}

Google OAuth 2.0 OIDC example for an app that runs on the localhost address at port 5001:

{
  "Local": {
    "Authority": "https://accounts.google.com/",
    "ClientId": "2.......7-e.....................q.apps.googleusercontent.com",
    "PostLogoutRedirectUri": "https://localhost:5001/authentication/logout-callback",
    "RedirectUri": "https://localhost:5001/authentication/login-callback",
    "ResponseType": "id_token"
  }
}

The redirect URI (https://localhost:5001/authentication/login-callback) is registered in the Google APIs console in Credentials > {NAME} > Authorized redirect URIs, where {NAME} is the app's client name in the OAuth 2.0 Client IDs app list of the Google APIs console.

Authentication support for standalone apps is offered using OpenID Connect (OIDC). The AddOidcAuthentication method accepts a callback to configure the parameters required to authenticate an app using OIDC. The values required for configuring the app can be obtained from the OIDC-compliant IP. Obtain the values when you register the app, which typically occurs in their online portal.

Access token scopes

The Blazor WebAssembly template automatically configures default scopes for openid and profile.

The Blazor WebAssembly template doesn't automatically configure the app to request an access token for a secure API. To provision an access token as part of the sign-in flow, add the scope to the default token scopes of the OidcProviderOptions. If adding authentication to an app, manually add the following code and configure the scope URI.

Program.cs:

builder.Services.AddOidcAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultScopes.Add("{SCOPE URI}");
});

For more information, see the following sections of the Additional scenarios article:

Imports file

The Microsoft.AspNetCore.Components.Authorization namespace is made available throughout the app via the _Imports.razor file:

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared

Index page

The Index page (wwwroot/index.html) page includes a script that defines the AuthenticationService in JavaScript. AuthenticationService handles the low-level details of the OIDC protocol. The app internally calls methods defined in the script to perform the authentication operations.

<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>

App component

The App component (App.razor) is similar to the App component found in Blazor Server apps:

  • The CascadingAuthenticationState component manages exposing the AuthenticationState to the rest of the app.
  • The AuthorizeRouteView component makes sure that the current user is authorized to access a given page or otherwise renders the RedirectToLogin component.
  • The RedirectToLogin component manages redirecting unauthorized users to the login page.

Due to changes in the framework across releases of ASP.NET Core, Razor markup for the App component (App.razor) isn't shown in this section. To inspect the markup of the component for a given release, use either of the following approaches:

  • Create an app provisioned for authentication from the default Blazor WebAssembly project template for the version of ASP.NET Core that you intend to use. Inspect the App component (App.razor) in the generated app.

  • Inspect the App component (App.razor) in reference source.

    Note

    Documentation links to .NET reference source usually 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).

RedirectToLogin component

The RedirectToLogin component (Shared/RedirectToLogin.razor):

  • Manages redirecting unauthorized users to the login page.
  • Preserves the current URL that the user is attempting to access so that they can be returned to that page if authentication is successful.
@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateTo(
            $"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
    }
}

LoginDisplay component

The LoginDisplay component (Shared/LoginDisplay.razor) is rendered in the MainLayout component (Shared/MainLayout.razor) and manages the following behaviors:

  • For authenticated users:
    • Displays the current username.
    • Offers a button to log out of the app.
  • For anonymous users, offers the option to log in.

Due to changes in the framework across releases of ASP.NET Core, Razor markup for the LoginDisplay component isn't shown in this section. To inspect the markup of the component for a given release, use either of the following approaches:

  • Create an app provisioned for authentication from the default Blazor WebAssembly project template for the version of ASP.NET Core that you intend to use. Inspect the LoginDisplay component in the generated app.

  • Inspect the LoginDisplay component in reference source.

    Note

    Documentation links to .NET reference source usually 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).

Authentication component

The page produced by the Authentication component (Pages/Authentication.razor) defines the routes required for handling different authentication stages.

The RemoteAuthenticatorView component:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string Action { get; set; }
}

Troubleshoot

Common errors

  • Misconfiguration of the app or Identity Provider (IP)

    The most common errors are caused by incorrect configuration. The following are a few examples:

    • Depending on the requirements of the scenario, a missing or incorrect Authority, Instance, Tenant ID, Tenant domain, Client ID, or Redirect URI prevents an app from authenticating clients.
    • An incorrect access token scope prevents clients from accessing server web API endpoints.
    • Incorrect or missing server API permissions prevent clients from accessing server web API endpoints.
    • Running the app at a different port than is configured in the Redirect URI of the Identity Provider's app registration.

    Configuration sections of this article's guidance show examples of the correct configuration. Carefully check each section of the article looking for app and IP misconfiguration.

    If the configuration appears correct:

    • Analyze application logs.

    • Examine the network traffic between the client app and the IP or server app with the browser's developer tools. Often, an exact error message or a message with a clue to what's causing the problem is returned to the client by the IP or server app after making a request. Developer tools guidance is found in the following articles:

    • Decode the contents of a JSON Web Token (JWT) used for authenticating a client or accessing a server web API, depending on where the problem is occurring. For more information, see Inspect the content of a JSON Web Token (JWT).

    The documentation team responds to document feedback and bugs in articles (open an issue from the This page feedback section) but is unable to provide product support. Several public support forums are available to assist with troubleshooting an app. We recommend the following:

    The preceding forums are not owned or controlled by Microsoft.

    For non-security, non-sensitive, and non-confidential reproducible framework bug reports, open an issue with the ASP.NET Core product unit. Don't open an issue with the product unit until you've thoroughly investigated the cause of a problem and can't resolve it on your own and with the help of the community on a public support forum. The product unit isn't able to troubleshoot individual apps that are broken due to simple misconfiguration or use cases involving third-party services. If a report is sensitive or confidential in nature or describes a potential security flaw in the product that attackers may exploit, see Reporting security issues and bugs (dotnet/aspnetcore GitHub repository).

  • Unauthorized client for AAD

    info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.

    Login callback error from AAD:

    • Error: unauthorized_client
    • Description: AADB2C90058: The provided application is not configured to allow public clients.

    To resolve the error:

    1. In the Azure portal, access the app's manifest.
    2. Set the allowPublicClient attribute to null or true.

Cookies and site data

Cookies and site data can persist across app updates and interfere with testing and troubleshooting. Clear the following when making app code changes, user account changes with the provider, or provider app configuration changes:

  • User sign-in cookies
  • App cookies
  • Cached and stored site data

One approach to prevent lingering cookies and site data from interfering with testing and troubleshooting is to:

  • Configure a browser
    • Use a browser for testing that you can configure to delete all cookie and site data each time the browser is closed.
    • Make sure that the browser is closed manually or by the IDE for any change to the app, test user, or provider configuration.
  • Use a custom command to open a browser in incognito or private mode in Visual Studio:
    • Open Browse With dialog box from Visual Studio's Run button.
    • Select the Add button.
    • Provide the path to your browser in the Program field. The following executable paths are typical installation locations for Windows 10. If your browser is installed in a different location or you aren't using Windows 10, provide the path to the browser's executable.
      • Microsoft Edge: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
      • Google Chrome: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      • Mozilla Firefox: C:\Program Files\Mozilla Firefox\firefox.exe
    • In the Arguments field, provide the command-line option that the browser uses to open in incognito or private mode. Some browsers require the URL of the app.
      • Microsoft Edge: Use -inprivate.
      • Google Chrome: Use --incognito --new-window {URL}, where the placeholder {URL} is the URL to open (for example, https://localhost:5001).
      • Mozilla Firefox: Use -private -url {URL}, where the placeholder {URL} is the URL to open (for example, https://localhost:5001).
    • Provide a name in the Friendly name field. For example, Firefox Auth Testing.
    • Select the OK button.
    • To avoid having to select the browser profile for each iteration of testing with an app, set the profile as the default with the Set as Default button.
    • Make sure that the browser is closed by the IDE for any change to the app, test user, or provider configuration.

App upgrades

A functioning app may fail immediately after upgrading either the .NET Core SDK on the development machine or changing package versions within the app. In some cases, incoherent packages may break an app when performing major upgrades. Most of these issues can be fixed by following these instructions:

  1. Clear the local system's NuGet package caches by executing dotnet nuget locals all --clear from a command shell.
  2. Delete the project's bin and obj folders.
  3. Restore and rebuild the project.
  4. Delete all of the files in the deployment folder on the server prior to redeploying the app.

Note

Use of package versions incompatible with the app's target framework isn't supported. For information on a package, use the NuGet Gallery or FuGet Package Explorer.

Run the Server app

When testing and troubleshooting a hosted Blazor WebAssembly solution, make sure that you're running the app from the Server project. For example in Visual Studio, confirm that the Server project is highlighted in Solution Explorer before you start the app with any of the following approaches:

  • Select the Run button.
  • Use Debug > Start Debugging from the menu.
  • Press F5.

Inspect the user

The ASP.NET Core framework's test assets include a Blazor WebAssembly client app with a User component that can be useful in troubleshooting. The User component can be used directly in apps or serve as the basis for further customization:

User test component in the dotnet/aspnetcore GitHub repository

Note

Documentation links to .NET reference source usually 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).

Inspect the content of a JSON Web Token (JWT)

To decode a JSON Web Token (JWT), use Microsoft's jwt.ms tool. Values in the UI never leave your browser.

Example encoded JWT (shortened for display):

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q

Example JWT decoded by the tool for an app that authenticates against Azure AAD B2C:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
  "exp": 1610059429,
  "nbf": 1610055829,
  "ver": "1.0",
  "iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
  "sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
  "aud": "70bde375-fce3-4b82-984a-b247d823a03f",
  "nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
  "iat": 1610055829,
  "auth_time": 1610055822,
  "idp": "idp.com",
  "tfp": "B2C_1_signupsignin"
}.[Signature]

Additional resources

For Azure Active Directory (AAD) and Azure Active Directory B2C (AAD B2C), don't follow the guidance in this topic. See the AAD and AAD B2C topics in this table of contents node.

To create a standalone Blazor WebAssembly app that uses Microsoft.AspNetCore.Components.WebAssembly.Authentication library, follow the guidance for your choice of tooling. If adding support for authentication, see the following sections of this article for guidance on setting up and configuring the app.

Note

The Identity Provider (IP) must use OpenID Connect (OIDC). For example, Facebook's IP isn't an OIDC-compliant provider, so the guidance in this topic doesn't work with the Facebook IP. For more information, see Secure ASP.NET Core Blazor WebAssembly.

To create a new Blazor WebAssembly project with an authentication mechanism:

  1. After choosing the Blazor WebAssembly App template in the Create a new ASP.NET Core Web Application dialog, select Change under Authentication.

  2. Select Individual User Accounts to use ASP.NET Core's Identity system. This selection adds authentication support and doesn't result in storing users in a database. The following sections of this article provide further details.

Authentication package

When an app is created to use Individual User Accounts, the app automatically receives a package reference for the Microsoft.AspNetCore.Components.WebAssembly.Authentication package. The package provides a set of primitives that help the app authenticate users and obtain tokens to call protected APIs.

If adding authentication to an app, manually add the Microsoft.AspNetCore.Components.WebAssembly.Authentication package to the app.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Authentication service support

Support for authenticating users is registered in the service container with the AddOidcAuthentication extension method provided by the Microsoft.AspNetCore.Components.WebAssembly.Authentication package. This method sets up the services required for the app to interact with the Identity Provider (IP).

For a new app, provide values for the {AUTHORITY} and {CLIENT ID} placeholders in the following configuration. Provide other configuration values that are required for use with the app's IP. The example is for Google, which requires PostLogoutRedirectUri, RedirectUri, and ResponseType. If adding authentication to an app, manually add the following code and configuration to the app with values for the placeholders and other configuration values.

Program.cs:

builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("Local", options.ProviderOptions);
});

Configuration is supplied by the wwwroot/appsettings.json file:

{
  "Local": {
    "Authority": "{AUTHORITY}",
    "ClientId": "{CLIENT ID}"
  }
}

Google OAuth 2.0 OIDC example for an app that runs on the localhost address at port 5001:

{
  "Local": {
    "Authority": "https://accounts.google.com/",
    "ClientId": "2.......7-e.....................q.apps.googleusercontent.com",
    "PostLogoutRedirectUri": "https://localhost:5001/authentication/logout-callback",
    "RedirectUri": "https://localhost:5001/authentication/login-callback",
    "ResponseType": "id_token"
  }
}

The redirect URI (https://localhost:5001/authentication/login-callback) is registered in the Google APIs console in Credentials > {NAME} > Authorized redirect URIs, where {NAME} is the app's client name in the OAuth 2.0 Client IDs app list of the Google APIs console.

Authentication support for standalone apps is offered using OpenID Connect (OIDC). The AddOidcAuthentication method accepts a callback to configure the parameters required to authenticate an app using OIDC. The values required for configuring the app can be obtained from the OIDC-compliant IP. Obtain the values when you register the app, which typically occurs in their online portal.

Access token scopes

The Blazor WebAssembly template automatically configures default scopes for openid and profile.

The Blazor WebAssembly template doesn't automatically configure the app to request an access token for a secure API. To provision an access token as part of the sign-in flow, add the scope to the default token scopes of the OidcProviderOptions. If adding authentication to an app, manually add the following code and configure the scope URI.

Program.cs:

builder.Services.AddOidcAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultScopes.Add("{SCOPE URI}");
});

For more information, see the following sections of the Additional scenarios article:

Imports file

The Microsoft.AspNetCore.Components.Authorization namespace is made available throughout the app via the _Imports.razor file:

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared

Index page

The Index page (wwwroot/index.html) page includes a script that defines the AuthenticationService in JavaScript. AuthenticationService handles the low-level details of the OIDC protocol. The app internally calls methods defined in the script to perform the authentication operations.

<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>

App component

The App component (App.razor) is similar to the App component found in Blazor Server apps:

  • The CascadingAuthenticationState component manages exposing the AuthenticationState to the rest of the app.
  • The AuthorizeRouteView component makes sure that the current user is authorized to access a given page or otherwise renders the RedirectToLogin component.
  • The RedirectToLogin component manages redirecting unauthorized users to the login page.

Due to changes in the framework across releases of ASP.NET Core, Razor markup for the App component (App.razor) isn't shown in this section. To inspect the markup of the component for a given release, use either of the following approaches:

  • Create an app provisioned for authentication from the default Blazor WebAssembly project template for the version of ASP.NET Core that you intend to use. Inspect the App component (App.razor) in the generated app.

  • Inspect the App component (App.razor) in reference source.

    Note

    Documentation links to .NET reference source usually 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).

RedirectToLogin component

The RedirectToLogin component (Shared/RedirectToLogin.razor):

  • Manages redirecting unauthorized users to the login page.
  • Preserves the current URL that the user is attempting to access so that they can be returned to that page if authentication is successful.
@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateTo(
            $"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
    }
}

LoginDisplay component

The LoginDisplay component (Shared/LoginDisplay.razor) is rendered in the MainLayout component (Shared/MainLayout.razor) and manages the following behaviors:

  • For authenticated users:
    • Displays the current username.
    • Offers a button to log out of the app.
  • For anonymous users, offers the option to log in.

Due to changes in the framework across releases of ASP.NET Core, Razor markup for the LoginDisplay component isn't shown in this section. To inspect the markup of the component for a given release, use either of the following approaches:

  • Create an app provisioned for authentication from the default Blazor WebAssembly project template for the version of ASP.NET Core that you intend to use. Inspect the LoginDisplay component in the generated app.

  • Inspect the LoginDisplay component in reference source.

    Note

    Documentation links to .NET reference source usually 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).

Authentication component

The page produced by the Authentication component (Pages/Authentication.razor) defines the routes required for handling different authentication stages.

The RemoteAuthenticatorView component:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string Action { get; set; }
}

Troubleshoot

Common errors

  • Misconfiguration of the app or Identity Provider (IP)

    The most common errors are caused by incorrect configuration. The following are a few examples:

    • Depending on the requirements of the scenario, a missing or incorrect Authority, Instance, Tenant ID, Tenant domain, Client ID, or Redirect URI prevents an app from authenticating clients.
    • An incorrect access token scope prevents clients from accessing server web API endpoints.
    • Incorrect or missing server API permissions prevent clients from accessing server web API endpoints.
    • Running the app at a different port than is configured in the Redirect URI of the Identity Provider's app registration.

    Configuration sections of this article's guidance show examples of the correct configuration. Carefully check each section of the article looking for app and IP misconfiguration.

    If the configuration appears correct:

    • Analyze application logs.

    • Examine the network traffic between the client app and the IP or server app with the browser's developer tools. Often, an exact error message or a message with a clue to what's causing the problem is returned to the client by the IP or server app after making a request. Developer tools guidance is found in the following articles:

    • Decode the contents of a JSON Web Token (JWT) used for authenticating a client or accessing a server web API, depending on where the problem is occurring. For more information, see Inspect the content of a JSON Web Token (JWT).

    The documentation team responds to document feedback and bugs in articles (open an issue from the This page feedback section) but is unable to provide product support. Several public support forums are available to assist with troubleshooting an app. We recommend the following:

    The preceding forums are not owned or controlled by Microsoft.

    For non-security, non-sensitive, and non-confidential reproducible framework bug reports, open an issue with the ASP.NET Core product unit. Don't open an issue with the product unit until you've thoroughly investigated the cause of a problem and can't resolve it on your own and with the help of the community on a public support forum. The product unit isn't able to troubleshoot individual apps that are broken due to simple misconfiguration or use cases involving third-party services. If a report is sensitive or confidential in nature or describes a potential security flaw in the product that attackers may exploit, see Reporting security issues and bugs (dotnet/aspnetcore GitHub repository).

  • Unauthorized client for AAD

    info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.

    Login callback error from AAD:

    • Error: unauthorized_client
    • Description: AADB2C90058: The provided application is not configured to allow public clients.

    To resolve the error:

    1. In the Azure portal, access the app's manifest.
    2. Set the allowPublicClient attribute to null or true.

Cookies and site data

Cookies and site data can persist across app updates and interfere with testing and troubleshooting. Clear the following when making app code changes, user account changes with the provider, or provider app configuration changes:

  • User sign-in cookies
  • App cookies
  • Cached and stored site data

One approach to prevent lingering cookies and site data from interfering with testing and troubleshooting is to:

  • Configure a browser
    • Use a browser for testing that you can configure to delete all cookie and site data each time the browser is closed.
    • Make sure that the browser is closed manually or by the IDE for any change to the app, test user, or provider configuration.
  • Use a custom command to open a browser in incognito or private mode in Visual Studio:
    • Open Browse With dialog box from Visual Studio's Run button.
    • Select the Add button.
    • Provide the path to your browser in the Program field. The following executable paths are typical installation locations for Windows 10. If your browser is installed in a different location or you aren't using Windows 10, provide the path to the browser's executable.
      • Microsoft Edge: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
      • Google Chrome: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      • Mozilla Firefox: C:\Program Files\Mozilla Firefox\firefox.exe
    • In the Arguments field, provide the command-line option that the browser uses to open in incognito or private mode. Some browsers require the URL of the app.
      • Microsoft Edge: Use -inprivate.
      • Google Chrome: Use --incognito --new-window {URL}, where the placeholder {URL} is the URL to open (for example, https://localhost:5001).
      • Mozilla Firefox: Use -private -url {URL}, where the placeholder {URL} is the URL to open (for example, https://localhost:5001).
    • Provide a name in the Friendly name field. For example, Firefox Auth Testing.
    • Select the OK button.
    • To avoid having to select the browser profile for each iteration of testing with an app, set the profile as the default with the Set as Default button.
    • Make sure that the browser is closed by the IDE for any change to the app, test user, or provider configuration.

App upgrades

A functioning app may fail immediately after upgrading either the .NET Core SDK on the development machine or changing package versions within the app. In some cases, incoherent packages may break an app when performing major upgrades. Most of these issues can be fixed by following these instructions:

  1. Clear the local system's NuGet package caches by executing dotnet nuget locals all --clear from a command shell.
  2. Delete the project's bin and obj folders.
  3. Restore and rebuild the project.
  4. Delete all of the files in the deployment folder on the server prior to redeploying the app.

Note

Use of package versions incompatible with the app's target framework isn't supported. For information on a package, use the NuGet Gallery or FuGet Package Explorer.

Run the Server app

When testing and troubleshooting a hosted Blazor WebAssembly solution, make sure that you're running the app from the Server project. For example in Visual Studio, confirm that the Server project is highlighted in Solution Explorer before you start the app with any of the following approaches:

  • Select the Run button.
  • Use Debug > Start Debugging from the menu.
  • Press F5.

Inspect the user

The ASP.NET Core framework's test assets include a Blazor WebAssembly client app with a User component that can be useful in troubleshooting. The User component can be used directly in apps or serve as the basis for further customization:

User test component in the dotnet/aspnetcore GitHub repository

Note

Documentation links to .NET reference source usually 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).

Inspect the content of a JSON Web Token (JWT)

To decode a JSON Web Token (JWT), use Microsoft's jwt.ms tool. Values in the UI never leave your browser.

Example encoded JWT (shortened for display):

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q

Example JWT decoded by the tool for an app that authenticates against Azure AAD B2C:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
  "exp": 1610059429,
  "nbf": 1610055829,
  "ver": "1.0",
  "iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
  "sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
  "aud": "70bde375-fce3-4b82-984a-b247d823a03f",
  "nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
  "iat": 1610055829,
  "auth_time": 1610055822,
  "idp": "idp.com",
  "tfp": "B2C_1_signupsignin"
}.[Signature]

Additional resources

For Azure Active Directory (AAD) and Azure Active Directory B2C (AAD B2C), don't follow the guidance in this topic. See the AAD and AAD B2C topics in this table of contents node.

To create a standalone Blazor WebAssembly app that uses Microsoft.AspNetCore.Components.WebAssembly.Authentication library, follow the guidance for your choice of tooling. If adding support for authentication, see the following sections of this article for guidance on setting up and configuring the app.

Note

The Identity Provider (IP) must use OpenID Connect (OIDC). For example, Facebook's IP isn't an OIDC-compliant provider, so the guidance in this topic doesn't work with the Facebook IP. For more information, see Secure ASP.NET Core Blazor WebAssembly.

To create a new Blazor WebAssembly project with an authentication mechanism:

  1. After choosing the Blazor WebAssembly App template in the Create a new ASP.NET Core Web Application dialog, select Change under Authentication.

  2. Select Individual User Accounts to use ASP.NET Core's Identity system. This selection adds authentication support and doesn't result in storing users in a database. The following sections of this article provide further details.

Authentication package

When an app is created to use Individual User Accounts, the app automatically receives a package reference for the Microsoft.AspNetCore.Components.WebAssembly.Authentication package. The package provides a set of primitives that help the app authenticate users and obtain tokens to call protected APIs.

If adding authentication to an app, manually add the Microsoft.AspNetCore.Components.WebAssembly.Authentication package to the app.

Note

For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.

Authentication service support

Support for authenticating users is registered in the service container with the AddOidcAuthentication extension method provided by the Microsoft.AspNetCore.Components.WebAssembly.Authentication package. This method sets up the services required for the app to interact with the Identity Provider (IP).

For a new app, provide values for the {AUTHORITY} and {CLIENT ID} placeholders in the following configuration. Provide other configuration values that are required for use with the app's IP. The example is for Google, which requires PostLogoutRedirectUri, RedirectUri, and ResponseType. If adding authentication to an app, manually add the following code and configuration to the app with values for the placeholders and other configuration values.

Program.cs:

builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("Local", options.ProviderOptions);
});

Configuration is supplied by the wwwroot/appsettings.json file:

{
  "Local": {
    "Authority": "{AUTHORITY}",
    "ClientId": "{CLIENT ID}"
  }
}

Google OAuth 2.0 OIDC example:

{
  "Local": {
    "Authority": "https://accounts.google.com/",
    "ClientId": "2.......7-e.....................q.apps.googleusercontent.com",
    "PostLogoutRedirectUri": "https://localhost:5001/authentication/logout-callback",
    "RedirectUri": "https://localhost:5001/authentication/login-callback",
    "ResponseType": "id_token"
  }
}

The redirect URI (https://localhost:5001/authentication/login-callback) is registered in the Google APIs console in Credentials > {NAME} > Authorized redirect URIs, where {NAME} is the app's client name in the OAuth 2.0 Client IDs app list of the Google APIs console.

Authentication support for standalone apps is offered using OpenID Connect (OIDC). The AddOidcAuthentication method accepts a callback to configure the parameters required to authenticate an app using OIDC. The values required for configuring the app can be obtained from the OIDC-compliant IP. Obtain the values when you register the app, which typically occurs in their online portal.

Access token scopes

The Blazor WebAssembly template automatically configures default scopes for openid and profile.

The Blazor WebAssembly template doesn't automatically configure the app to request an access token for a secure API. To provision an access token as part of the sign-in flow, add the scope to the default token scopes of the OidcProviderOptions. If adding authentication to an app, manually add the following code and configure the scope URI.

Program.cs:

builder.Services.AddOidcAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultScopes.Add("{SCOPE URI}");
});

For more information, see the following sections of the Additional scenarios article:

Imports file

The Microsoft.AspNetCore.Components.Authorization namespace is made available throughout the app via the _Imports.razor file:

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared

Index page

The Index page (wwwroot/index.html) page includes a script that defines the AuthenticationService in JavaScript. AuthenticationService handles the low-level details of the OIDC protocol. The app internally calls methods defined in the script to perform the authentication operations.

<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>

App component

The App component (App.razor) is similar to the App component found in Blazor Server apps:

  • The CascadingAuthenticationState component manages exposing the AuthenticationState to the rest of the app.
  • The AuthorizeRouteView component makes sure that the current user is authorized to access a given page or otherwise renders the RedirectToLogin component.
  • The RedirectToLogin component manages redirecting unauthorized users to the login page.

Due to changes in the framework across releases of ASP.NET Core, Razor markup for the App component (App.razor) isn't shown in this section. To inspect the markup of the component for a given release, use either of the following approaches:

  • Create an app provisioned for authentication from the default Blazor WebAssembly project template for the version of ASP.NET Core that you intend to use. Inspect the App component (App.razor) in the generated app.

  • Inspect the App component (App.razor) in reference source.

    Note

    Documentation links to .NET reference source usually 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).

RedirectToLogin component

The RedirectToLogin component (Shared/RedirectToLogin.razor):

  • Manages redirecting unauthorized users to the login page.
  • Preserves the current URL that the user is attempting to access so that they can be returned to that page if authentication is successful.
@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateTo(
            $"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
    }
}

LoginDisplay component

The LoginDisplay component (Shared/LoginDisplay.razor) is rendered in the MainLayout component (Shared/MainLayout.razor) and manages the following behaviors:

  • For authenticated users:
    • Displays the current username.
    • Offers a button to log out of the app.
  • For anonymous users, offers the option to log in.

Due to changes in the framework across releases of ASP.NET Core, Razor markup for the LoginDisplay component isn't shown in this section. To inspect the markup of the component for a given release, use either of the following approaches:

  • Create an app provisioned for authentication from the default Blazor WebAssembly project template for the version of ASP.NET Core that you intend to use. Inspect the LoginDisplay component in the generated app.

  • Inspect the LoginDisplay component in reference source.

    Note

    Documentation links to .NET reference source usually 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).

Authentication component

The page produced by the Authentication component (Pages/Authentication.razor) defines the routes required for handling different authentication stages.

The RemoteAuthenticatorView component:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string Action { get; set; }
}

Troubleshoot

Common errors

  • Misconfiguration of the app or Identity Provider (IP)

    The most common errors are caused by incorrect configuration. The following are a few examples:

    • Depending on the requirements of the scenario, a missing or incorrect Authority, Instance, Tenant ID, Tenant domain, Client ID, or Redirect URI prevents an app from authenticating clients.
    • An incorrect access token scope prevents clients from accessing server web API endpoints.
    • Incorrect or missing server API permissions prevent clients from accessing server web API endpoints.
    • Running the app at a different port than is configured in the Redirect URI of the Identity Provider's app registration.

    Configuration sections of this article's guidance show examples of the correct configuration. Carefully check each section of the article looking for app and IP misconfiguration.

    If the configuration appears correct:

    • Analyze application logs.

    • Examine the network traffic between the client app and the IP or server app with the browser's developer tools. Often, an exact error message or a message with a clue to what's causing the problem is returned to the client by the IP or server app after making a request. Developer tools guidance is found in the following articles:

    • Decode the contents of a JSON Web Token (JWT) used for authenticating a client or accessing a server web API, depending on where the problem is occurring. For more information, see Inspect the content of a JSON Web Token (JWT).

    The documentation team responds to document feedback and bugs in articles (open an issue from the This page feedback section) but is unable to provide product support. Several public support forums are available to assist with troubleshooting an app. We recommend the following:

    The preceding forums are not owned or controlled by Microsoft.

    For non-security, non-sensitive, and non-confidential reproducible framework bug reports, open an issue with the ASP.NET Core product unit. Don't open an issue with the product unit until you've thoroughly investigated the cause of a problem and can't resolve it on your own and with the help of the community on a public support forum. The product unit isn't able to troubleshoot individual apps that are broken due to simple misconfiguration or use cases involving third-party services. If a report is sensitive or confidential in nature or describes a potential security flaw in the product that attackers may exploit, see Reporting security issues and bugs (dotnet/aspnetcore GitHub repository).

  • Unauthorized client for AAD

    info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.

    Login callback error from AAD:

    • Error: unauthorized_client
    • Description: AADB2C90058: The provided application is not configured to allow public clients.

    To resolve the error:

    1. In the Azure portal, access the app's manifest.
    2. Set the allowPublicClient attribute to null or true.

Cookies and site data

Cookies and site data can persist across app updates and interfere with testing and troubleshooting. Clear the following when making app code changes, user account changes with the provider, or provider app configuration changes:

  • User sign-in cookies
  • App cookies
  • Cached and stored site data

One approach to prevent lingering cookies and site data from interfering with testing and troubleshooting is to:

  • Configure a browser
    • Use a browser for testing that you can configure to delete all cookie and site data each time the browser is closed.
    • Make sure that the browser is closed manually or by the IDE for any change to the app, test user, or provider configuration.
  • Use a custom command to open a browser in incognito or private mode in Visual Studio:
    • Open Browse With dialog box from Visual Studio's Run button.
    • Select the Add button.
    • Provide the path to your browser in the Program field. The following executable paths are typical installation locations for Windows 10. If your browser is installed in a different location or you aren't using Windows 10, provide the path to the browser's executable.
      • Microsoft Edge: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
      • Google Chrome: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      • Mozilla Firefox: C:\Program Files\Mozilla Firefox\firefox.exe
    • In the Arguments field, provide the command-line option that the browser uses to open in incognito or private mode. Some browsers require the URL of the app.
      • Microsoft Edge: Use -inprivate.
      • Google Chrome: Use --incognito --new-window {URL}, where the placeholder {URL} is the URL to open (for example, https://localhost:5001).
      • Mozilla Firefox: Use -private -url {URL}, where the placeholder {URL} is the URL to open (for example, https://localhost:5001).
    • Provide a name in the Friendly name field. For example, Firefox Auth Testing.
    • Select the OK button.
    • To avoid having to select the browser profile for each iteration of testing with an app, set the profile as the default with the Set as Default button.
    • Make sure that the browser is closed by the IDE for any change to the app, test user, or provider configuration.

App upgrades

A functioning app may fail immediately after upgrading either the .NET Core SDK on the development machine or changing package versions within the app. In some cases, incoherent packages may break an app when performing major upgrades. Most of these issues can be fixed by following these instructions:

  1. Clear the local system's NuGet package caches by executing dotnet nuget locals all --clear from a command shell.
  2. Delete the project's bin and obj folders.
  3. Restore and rebuild the project.
  4. Delete all of the files in the deployment folder on the server prior to redeploying the app.

Note

Use of package versions incompatible with the app's target framework isn't supported. For information on a package, use the NuGet Gallery or FuGet Package Explorer.

Run the Server app

When testing and troubleshooting a hosted Blazor WebAssembly solution, make sure that you're running the app from the Server project. For example in Visual Studio, confirm that the Server project is highlighted in Solution Explorer before you start the app with any of the following approaches:

  • Select the Run button.
  • Use Debug > Start Debugging from the menu.
  • Press F5.

Inspect the user

The ASP.NET Core framework's test assets include a Blazor WebAssembly client app with a User component that can be useful in troubleshooting. The User component can be used directly in apps or serve as the basis for further customization:

User test component in the dotnet/aspnetcore GitHub repository

Note

Documentation links to .NET reference source usually 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).

Inspect the content of a JSON Web Token (JWT)

To decode a JSON Web Token (JWT), use Microsoft's jwt.ms tool. Values in the UI never leave your browser.

Example encoded JWT (shortened for display):

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q

Example JWT decoded by the tool for an app that authenticates against Azure AAD B2C:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
  "exp": 1610059429,
  "nbf": 1610055829,
  "ver": "1.0",
  "iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
  "sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
  "aud": "70bde375-fce3-4b82-984a-b247d823a03f",
  "nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
  "iat": 1610055829,
  "auth_time": 1610055822,
  "idp": "idp.com",
  "tfp": "B2C_1_signupsignin"
}.[Signature]

Additional resources