Secure an ASP.NET Core Blazor WebAssembly standalone app with Azure Active Directory
This article covers how to create a standalone Blazor WebAssembly app that uses Azure Active Directory (AAD) for authentication.
Note
For Blazor WebAssembly apps created in Visual Studio that are configured to support accounts in an AAD organizational directory with Microsoft Identity Platform, use Visual Studio version 16.10 or later in order to create the app with the correct Azure configuration. If you use a version of Visual Studio earlier than 16.10, you must manually update the app's configuration per each section of this article after generating the app.
Register an AAD app:
- Navigate to Azure Active Directory in the Azure portal. Select App registrations in the sidebar. Select the New registration button.
- Provide a Name for the app (for example, Blazor Standalone AAD).
- Choose a Supported account types. You may select Accounts in this organizational directory only for this experience.
- Set the Redirect URI drop down to Single-page application (SPA) and provide the following redirect URI:
https://localhost:{PORT}/authentication/login-callback. The default port for an app running on Kestrel is 5001. If the app is run on a different Kestrel port, use the app's port. For IIS Express, the randomly generated port for the app can be found in the app's properties in the Debug panel. Since the app doesn't exist at this point and the IIS Express port isn't known, return to this step after the app is created and update the redirect URI. A remark appears later in this topic to remind IIS Express users to update the redirect URI. - If you're using an unverified publisher domain, clear the Permissions > Grant admin consent to openid and offline_access permissions checkbox. If the publisher domain is verified, this checkbox isn't present.
- Select Register.
Record the following information:
- Application (client) ID (for example,
41451fa7-82d9-4673-8fa5-69eff5a761fd) - Directory (tenant) ID (for example,
e86c78e2-8bb4-4c41-aefd-918e0565a45e)
In Authentication > Platform configurations > Single-page application (SPA):
- Confirm the Redirect URI of
https://localhost:{PORT}/authentication/login-callbackis present. - For Implicit grant, ensure that the checkboxes for Access tokens and ID tokens are not selected.
- The remaining defaults for the app are acceptable for this experience.
- Select the Save button.
Create the app in an empty folder. Replace the placeholders in the following command with the information recorded earlier and execute the command in a command shell:
dotnet new blazorwasm -au SingleOrg --client-id "{CLIENT ID}" -o {APP NAME} --tenant-id "{TENANT ID}"
| Placeholder | Azure portal name | Example |
|---|---|---|
{APP NAME} |
— | BlazorSample |
{CLIENT ID} |
Application (client) ID | 41451fa7-82d9-4673-8fa5-69eff5a761fd |
{TENANT ID} |
Directory (tenant) ID | e86c78e2-8bb4-4c41-aefd-918e0565a45e |
The output location specified with the -o|--output option creates a project folder if it doesn't exist and becomes part of the app's name.
Note
In the Azure portal, the app's platform configuration Redirect URI is configured for port 5001 for apps that run on the Kestrel server with default settings.
If the app is run on a random IIS Express port, the port for the app can be found in the app's properties in the Debug panel.
If the port wasn't configured earlier with the app's known port, return to the app's registration in the Azure portal and update the redirect URI with the correct port.
Add a MsalProviderOptions for User.Read permission with DefaultAccessTokenScopes:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes
.Add("https://graph.microsoft.com/User.Read");
});
After creating the app, you should be able to:
- Log into the app using an AAD user account.
- Request access tokens for Microsoft APIs. For more information, see:
Authentication package
When an app is created to use Work or School Accounts (SingleOrg), the app automatically receives a package reference for the Microsoft Authentication Library (Microsoft.Authentication.WebAssembly.Msal). 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 package to the app's project file:
<PackageReference Include="Microsoft.Authentication.WebAssembly.Msal"
Version="{VERSION}" />
For the placeholder {VERSION}, the latest stable version of the package that matches the app's shared framework version can be found in the package's Version History at NuGet.org.
The Microsoft.Authentication.WebAssembly.Msal package transitively adds the Microsoft.AspNetCore.Components.WebAssembly.Authentication package to the app.
Authentication service support
Support for authenticating users is registered in the service container with the AddMsalAuthentication extension method provided by the Microsoft.Authentication.WebAssembly.Msal package. This method sets up the services required for the app to interact with the Identity Provider (IP).
Program.cs:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
});
The AddMsalAuthentication method accepts a callback to configure the parameters required to authenticate an app. The values required for configuring the app can be obtained from the AAD configuration when you register the app.
Configuration is supplied by the wwwroot/appsettings.json file:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/{TENANT ID}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": true
}
}
Example:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/e86c78e2-...-918e0565a45e",
"ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
"ValidateAuthority": true
}
}
Access token scopes
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 access token scopes of the MsalProviderOptions:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});
Specify additional scopes with AdditionalScopesToConsent:
options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");
For more information, see the following sections of the Additional scenarios article:
Login mode
The framework defaults to pop-up login mode and falls back to redirect login mode if a pop-up can't be opened. Configure MSAL to use redirect login mode by setting the LoginMode property of MsalProviderOptions to redirect:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.LoginMode = "redirect";
});
The default setting is popup, and the string value isn't case sensitive.
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.Authentication.WebAssembly.Msal/
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
RedirectToLogincomponent. - The
RedirectToLogincomponent 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
Appcomponent (App.razor) in the generated app.Inspect the
Appcomponent (App.razor) in reference source.Note
Documentation links to the ASP.NET Core reference source load the repository's
mainbranch, which represents the product unit's current development for the next release of ASP.NET Core. To select the branch for a different release, use the Switch branches or tags dropdown list to select the branch. For example, select therelease/6.0branch for the ASP.NET Core 6.0 release.
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.
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<button class="nav-link btn btn-link" @onclick="BeginLogout">
Log out
</button>
</Authorized>
<NotAuthorized>
<a href="authentication/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
@code {
private async Task BeginLogout(MouseEventArgs args)
{
await SignOutManager.SetSignOutState();
Navigation.NavigateTo("authentication/logout");
}
}
Authentication component
The page produced by the Authentication component (Pages/Authentication.razor) defines the routes required for handling different authentication stages.
The RemoteAuthenticatorView component:
- Is provided by the
Microsoft.AspNetCore.Components.WebAssembly.Authenticationpackage. - Manages performing the appropriate actions at each stage of authentication.
@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:
- Google Chrome (Google documentation)
- Microsoft Edge
- Mozilla Firefox (Mozilla documentation)
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 documenation 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:
- In the Azure portal, access the app's manifest.
- Set the
allowPublicClientattribute tonullortrue.
- Error:
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
- Microsoft Edge:
- 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).
- Microsoft Edge: Use
- 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:
- Clear the local system's NuGet package caches by executing
dotnet nuget locals all --clearfrom a command shell. - Delete the project's
binandobjfolders. - Restore and rebuild the project.
- 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 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 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
- ASP.NET Core Blazor WebAssembly additional security scenarios
- Build a custom version of the Authentication.MSAL JavaScript library
- Unauthenticated or unauthorized web API requests in an app with a secure default client
- ASP.NET Core Blazor WebAssembly with Azure Active Directory groups and roles
- Microsoft identity platform and Azure Active Directory with ASP.NET Core
- Microsoft identity platform documentation
This article covers how to create a standalone Blazor WebAssembly app that uses Azure Active Directory (AAD) for authentication.
Note
For Blazor WebAssembly apps created in Visual Studio that are configured to support accounts in an AAD organizational directory with Microsoft Identity Platform, use Visual Studio version 16.10 or later in order to create the app with the correct Azure configuration. If you use a version of Visual Studio earlier than 16.10, you must manually update the app's configuration per each section of this article after generating the app.
Register an AAD app:
- Navigate to Azure Active Directory in the Azure portal. Select App registrations in the sidebar. Select the New registration button.
- Provide a Name for the app (for example, Blazor Standalone AAD).
- Choose a Supported account types. You may select Accounts in this organizational directory only for this experience.
- Set the Redirect URI drop down to Single-page application (SPA) and provide the following redirect URI:
https://localhost:{PORT}/authentication/login-callback. The default port for an app running on Kestrel is 5001. If the app is run on a different Kestrel port, use the app's port. For IIS Express, the randomly generated port for the app can be found in the app's properties in the Debug panel. Since the app doesn't exist at this point and the IIS Express port isn't known, return to this step after the app is created and update the redirect URI. A remark appears later in this topic to remind IIS Express users to update the redirect URI. - If you're using an unverified publisher domain, clear the Permissions > Grant admin consent to openid and offline_access permissions checkbox. If the publisher domain is verified, this checkbox isn't present.
- Select Register.
Record the following information:
- Application (client) ID (for example,
41451fa7-82d9-4673-8fa5-69eff5a761fd) - Directory (tenant) ID (for example,
e86c78e2-8bb4-4c41-aefd-918e0565a45e)
In Authentication > Platform configurations > Single-page application (SPA):
- Confirm the Redirect URI of
https://localhost:{PORT}/authentication/login-callbackis present. - For Implicit grant, ensure that the checkboxes for Access tokens and ID tokens are not selected.
- The remaining defaults for the app are acceptable for this experience.
- Select the Save button.
Create the app in an empty folder. Replace the placeholders in the following command with the information recorded earlier and execute the command in a command shell:
dotnet new blazorwasm -au SingleOrg --client-id "{CLIENT ID}" -o {APP NAME} --tenant-id "{TENANT ID}"
| Placeholder | Azure portal name | Example |
|---|---|---|
{APP NAME} |
— | BlazorSample |
{CLIENT ID} |
Application (client) ID | 41451fa7-82d9-4673-8fa5-69eff5a761fd |
{TENANT ID} |
Directory (tenant) ID | e86c78e2-8bb4-4c41-aefd-918e0565a45e |
The output location specified with the -o|--output option creates a project folder if it doesn't exist and becomes part of the app's name.
Note
In the Azure portal, the app's platform configuration Redirect URI is configured for port 5001 for apps that run on the Kestrel server with default settings.
If the app is run on a random IIS Express port, the port for the app can be found in the app's properties in the Debug panel.
If the port wasn't configured earlier with the app's known port, return to the app's registration in the Azure portal and update the redirect URI with the correct port.
Add a MsalProviderOptions for User.Read permission with DefaultAccessTokenScopes:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes
.Add("https://graph.microsoft.com/User.Read");
});
After creating the app, you should be able to:
- Log into the app using an AAD user account.
- Request access tokens for Microsoft APIs. For more information, see:
Authentication package
When an app is created to use Work or School Accounts (SingleOrg), the app automatically receives a package reference for the Microsoft Authentication Library (Microsoft.Authentication.WebAssembly.Msal). 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 package to the app's project file:
<PackageReference Include="Microsoft.Authentication.WebAssembly.Msal"
Version="{VERSION}" />
For the placeholder {VERSION}, the latest stable version of the package that matches the app's shared framework version can be found in the package's Version History at NuGet.org.
The Microsoft.Authentication.WebAssembly.Msal package transitively adds the Microsoft.AspNetCore.Components.WebAssembly.Authentication package to the app.
Authentication service support
Support for authenticating users is registered in the service container with the AddMsalAuthentication extension method provided by the Microsoft.Authentication.WebAssembly.Msal package. This method sets up the services required for the app to interact with the Identity Provider (IP).
Program.cs:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
});
The AddMsalAuthentication method accepts a callback to configure the parameters required to authenticate an app. The values required for configuring the app can be obtained from the AAD configuration when you register the app.
Configuration is supplied by the wwwroot/appsettings.json file:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/{TENANT ID}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": true
}
}
Example:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/e86c78e2-...-918e0565a45e",
"ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
"ValidateAuthority": true
}
}
Access token scopes
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 access token scopes of the MsalProviderOptions:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});
Specify additional scopes with AdditionalScopesToConsent:
options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");
For more information, see the following sections of the Additional scenarios article:
Login mode
The framework defaults to pop-up login mode and falls back to redirect login mode if a pop-up can't be opened. Configure MSAL to use redirect login mode by setting the LoginMode property of MsalProviderOptions to redirect:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.LoginMode = "redirect";
});
The default setting is popup, and the string value isn't case sensitive.
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.Authentication.WebAssembly.Msal/
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
RedirectToLogincomponent. - The
RedirectToLogincomponent 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
Appcomponent (App.razor) in the generated app.Inspect the
Appcomponent (App.razor) in reference source.Note
Documentation links to the ASP.NET Core reference source load the repository's
mainbranch, which represents the product unit's current development for the next release of ASP.NET Core. To select the branch for a different release, use the Switch branches or tags dropdown list to select the branch. For example, select therelease/6.0branch for the ASP.NET Core 6.0 release.
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.
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<button class="nav-link btn btn-link" @onclick="BeginLogout">
Log out
</button>
</Authorized>
<NotAuthorized>
<a href="authentication/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
@code {
private async Task BeginLogout(MouseEventArgs args)
{
await SignOutManager.SetSignOutState();
Navigation.NavigateTo("authentication/logout");
}
}
Authentication component
The page produced by the Authentication component (Pages/Authentication.razor) defines the routes required for handling different authentication stages.
The RemoteAuthenticatorView component:
- Is provided by the
Microsoft.AspNetCore.Components.WebAssembly.Authenticationpackage. - Manages performing the appropriate actions at each stage of authentication.
@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:
- Google Chrome (Google documentation)
- Microsoft Edge
- Mozilla Firefox (Mozilla documentation)
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 documenation 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:
- In the Azure portal, access the app's manifest.
- Set the
allowPublicClientattribute tonullortrue.
- Error:
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
- Microsoft Edge:
- 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).
- Microsoft Edge: Use
- 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:
- Clear the local system's NuGet package caches by executing
dotnet nuget locals all --clearfrom a command shell. - Delete the project's
binandobjfolders. - Restore and rebuild the project.
- 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 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 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
- ASP.NET Core Blazor WebAssembly additional security scenarios
- Build a custom version of the Authentication.MSAL JavaScript library
- Unauthenticated or unauthorized web API requests in an app with a secure default client
- ASP.NET Core Blazor WebAssembly with Azure Active Directory groups and roles
- Microsoft identity platform and Azure Active Directory with ASP.NET Core
- Microsoft identity platform documentation
This article covers how to create a standalone Blazor WebAssembly app that uses Azure Active Directory (AAD) for authentication.
Register an AAD app:
- Navigate to Azure Active Directory in the Azure portal. Select App registrations in the sidebar. Select the New registration button.
- Provide a Name for the app (for example, Blazor Standalone AAD).
- Choose a Supported account types. You may select Accounts in this organizational directory only for this experience.
- Leave the Redirect URI drop down set to Web and provide the following redirect URI:
https://localhost:{PORT}/authentication/login-callback. The default port for an app running on Kestrel is 5001. If the app is run on a different Kestrel port, use the app's port. For IIS Express, the randomly generated port for the app can be found in the app's properties in the Debug panel. Since the app doesn't exist at this point and the IIS Express port isn't known, return to this step after the app is created and update the redirect URI. A remark appears later in this topic to remind IIS Express users to update the redirect URI. - If you're using an unverified publisher domain, clear the Permissions > Grant admin consent to openid and offline_access permissions checkbox. If the publisher domain is verified, this checkbox isn't present.
- Select Register.
Record the following information:
- Application (client) ID (for example,
41451fa7-82d9-4673-8fa5-69eff5a761fd) - Directory (tenant) ID (for example,
e86c78e2-8bb4-4c41-aefd-918e0565a45e)
In Authentication > Platform configurations > Web:
- Confirm the Redirect URI of
https://localhost:{PORT}/authentication/login-callbackis present. - For Implicit grant, select the checkboxes for Access tokens and ID tokens.
- The remaining defaults for the app are acceptable for this experience.
- Select the Save button.
Create the app in an empty folder. Replace the placeholders in the following command with the information recorded earlier and execute the command in a command shell:
dotnet new blazorwasm -au SingleOrg --client-id "{CLIENT ID}" -o {APP NAME} --tenant-id "{TENANT ID}"
| Placeholder | Azure portal name | Example |
|---|---|---|
{APP NAME} |
— | BlazorSample |
{CLIENT ID} |
Application (client) ID | 41451fa7-82d9-4673-8fa5-69eff5a761fd |
{TENANT ID} |
Directory (tenant) ID | e86c78e2-8bb4-4c41-aefd-918e0565a45e |
The output location specified with the -o|--output option creates a project folder if it doesn't exist and becomes part of the app's name.
Note
In the Azure portal, the app's platform configuration Redirect URI is configured for port 5001 for apps that run on the Kestrel server with default settings.
If the app is run on a random IIS Express port, the port for the app can be found in the app's properties in the Debug panel.
If the port wasn't configured earlier with the app's known port, return to the app's registration in the Azure portal and update the redirect URI with the correct port.
After creating the app, you should be able to:
- Log into the app using an AAD user account.
- Request access tokens for Microsoft APIs. For more information, see:
Authentication package
When an app is created to use Work or School Accounts (SingleOrg), the app automatically receives a package reference for the Microsoft Authentication Library (Microsoft.Authentication.WebAssembly.Msal). 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 package to the app's project file:
<PackageReference Include="Microsoft.Authentication.WebAssembly.Msal"
Version="{VERSION}" />
For the placeholder {VERSION}, the latest stable version of the package that matches the app's shared framework version can be found in the package's Version History at NuGet.org.
The Microsoft.Authentication.WebAssembly.Msal package transitively adds the Microsoft.AspNetCore.Components.WebAssembly.Authentication package to the app.
Authentication service support
Support for authenticating users is registered in the service container with the AddMsalAuthentication extension method provided by the Microsoft.Authentication.WebAssembly.Msal package. This method sets up the services required for the app to interact with the Identity Provider (IP).
Program.cs:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
});
The AddMsalAuthentication method accepts a callback to configure the parameters required to authenticate an app. The values required for configuring the app can be obtained from the AAD configuration when you register the app.
Configuration is supplied by the wwwroot/appsettings.json file:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/{TENANT ID}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": true
}
}
Example:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/e86c78e2-...-918e0565a45e",
"ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
"ValidateAuthority": true
}
}
Access token scopes
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 access token scopes of the MsalProviderOptions:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});
Specify additional scopes with AdditionalScopesToConsent:
options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");
When working with a server API registered with AAD and the app's AAD registration is in an tenant that relies on an unverified publisher domain, the App ID URI of your server API app isn't api://{SERVER API APP CLIENT ID OR CUSTOM VALUE} but instead is in the format https://{TENANT}.onmicrosoft.com/{SERVER API APP CLIENT ID OR CUSTOM VALUE}. If that's the case, the default access token scope in Program.cs of the Client app appears similar to the following:
options.ProviderOptions.DefaultAccessTokenScopes
.Add("https://{TENANT}.onmicrosoft.com/{SERVER API APP CLIENT ID OR CUSTOM VALUE}/{DEFAULT SCOPE}");
To configure the server API app for a matching audience, set the Audience in the Server API app settings file (appsettings.json) to match the app's audience provided by the Azure portal:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/{TENANT ID}",
"ClientId": "{SERVER API APP CLIENT ID}",
"ValidateAuthority": true,
"Audience": "https://{TENANT}.onmicrosoft.com/{SERVER API APP CLIENT ID OR CUSTOM VALUE}"
}
}
In the preceding configuration, the end of the Audience value does not include the default scope /{DEFAULT SCOPE}.
Example:
In Program.cs of the Client app:
options.ProviderOptions.DefaultAccessTokenScopes
.Add("https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
Configure the Server API app settings file (appsettings.json) with a matching audience (Audience):
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/e86c78e2-...-918e0565a45e",
"ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
"ValidateAuthority": true,
"Audience": "https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd"
}
}
In the preceding example, the end of the Audience value does not include the default scope /API.Access.
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.Authentication.WebAssembly.Msal/
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
RedirectToLogincomponent. - The
RedirectToLogincomponent 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
Appcomponent (App.razor) in the generated app.Inspect the
Appcomponent (App.razor) in reference source.Note
Documentation links to the ASP.NET Core reference source load the repository's
mainbranch, which represents the product unit's current development for the next release of ASP.NET Core. To select the branch for a different release, use the Switch branches or tags dropdown list to select the branch. For example, select therelease/6.0branch for the ASP.NET Core 6.0 release.
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.
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<button class="nav-link btn btn-link" @onclick="BeginLogout">
Log out
</button>
</Authorized>
<NotAuthorized>
<a href="authentication/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
@code {
private async Task BeginLogout(MouseEventArgs args)
{
await SignOutManager.SetSignOutState();
Navigation.NavigateTo("authentication/logout");
}
}
Authentication component
The page produced by the Authentication component (Pages/Authentication.razor) defines the routes required for handling different authentication stages.
The RemoteAuthenticatorView component:
- Is provided by the
Microsoft.AspNetCore.Components.WebAssembly.Authenticationpackage. - Manages performing the appropriate actions at each stage of authentication.
@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:
- Google Chrome (Google documentation)
- Microsoft Edge
- Mozilla Firefox (Mozilla documentation)
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 documenation 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:
- In the Azure portal, access the app's manifest.
- Set the
allowPublicClientattribute tonullortrue.
- Error:
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
- Microsoft Edge:
- 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).
- Microsoft Edge: Use
- 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:
- Clear the local system's NuGet package caches by executing
dotnet nuget locals all --clearfrom a command shell. - Delete the project's
binandobjfolders. - Restore and rebuild the project.
- 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 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 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
- ASP.NET Core Blazor WebAssembly additional security scenarios
- Build a custom version of the Authentication.MSAL JavaScript library
- Unauthenticated or unauthorized web API requests in an app with a secure default client
- ASP.NET Core Blazor WebAssembly with Azure Active Directory groups and roles
- Microsoft identity platform and Azure Active Directory with ASP.NET Core
- Microsoft identity platform documentation