aspnetcore/blazor/security/webassembly/standalone-with-azure-active-directory-b2c.md
This article explains how to create a standalone Blazor WebAssembly app that uses Azure Active Directory (AAD) B2C for authentication.
For additional security scenario coverage after reading this article, see xref:blazor/security/webassembly/additional-scenarios.
The subsections of the walkthrough explain how to:
Follow the guidance in Tutorial: Create an Azure Active Directory B2C tenant to create an AAD B2C tenant.
Before proceeding with this article's guidance, confirm that you've selected the correct directory for the AAD B2C tenant.
Register an AAD B2C app:
https://localhost/authentication/login-callback. If you know the production redirect URI for the Azure default host (for example, azurewebsites.net) or the custom domain host (for example, contoso.com), you can also add the production redirect URI at the same time that you're providing the localhost redirect URI. Be sure to include the port number for non-:443 ports in any production redirect URIs that you add.[!NOTE] Supplying the port number for a
localhostAAD B2C redirect URI isn't required. For more information, see Redirect URI (reply URL) restrictions and limitations: Localhost exceptions (Entra documentation).
Record the following information:
00001111-aaaa-2222-bbbb-3333cccc4444).https://contoso.b2clogin.com/, which includes the trailing slash): The instance is the scheme and host of an Azure B2C app registration, which can be found by opening the Endpoints window from the App registrations page in the Azure portal.contoso.onmicrosoft.com): The domain is available as the Publisher domain in the Branding blade of the Azure portal for the registered app.In Authentication > Platform configurations > Single-page application:
https://localhost/authentication/login-callback is present.In Home > Azure AD B2C > User flows:
Create a sign-up and sign-in user flow
At a minimum, select the Application claims > Display Name user attribute to populate the context.User.Identity?.Name/context.User.Identity.Name in the LoginDisplay component (Shared/LoginDisplay.razor).
Record the sign-up and sign-in user flow name created for the app (for example, B2C_1_signupsignin).
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 IndividualB2C --aad-b2c-instance "{AAD B2C INSTANCE}" --client-id "{CLIENT ID}" --domain "{TENANT DOMAIN}" -o {PROJECT NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"
| Placeholder | Azure portal name | Example |
|---|---|---|
{AAD B2C INSTANCE} | Instance | https://contoso.b2clogin.com/ (includes the trailing slash) |
{PROJECT NAME} | — | BlazorSample |
{CLIENT ID} | Application (client) ID | 00001111-aaaa-2222-bbbb-3333cccc4444 |
{SIGN UP OR SIGN IN POLICY} | Sign-up/sign-in user flow | B2C_1_signupsignin1 |
{TENANT DOMAIN} | Primary/Publisher/Tenant domain | contoso.onmicrosoft.com |
The output location specified with the -o|--output option creates a project folder if it doesn't exist and becomes part of the project's name.
After creating the app, you should be able to:
Use one of the following approaches to run the app:
dotnet watch (or dotnet run) command from the app's folder.This section describes the parts of an app generated from the Blazor WebAssembly project template and how the app is configured. There's no specific guidance to follow in this section for a basic working application if you created the app using the guidance in the Walkthrough section. The guidance in this section is helpful for updating an app to authenticate and authorize users. However, an alternative approach to updating an app is to create a new app from the guidance in the Walkthrough section and moving the app's components, classes, and resources to the new app.
When an app is created to use an Individual B2C Account (IndividualB2C), 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 Microsoft.Authentication.WebAssembly.Msal package to the app.
The Microsoft.Authentication.WebAssembly.Msal package transitively adds the Microsoft.AspNetCore.Components.WebAssembly.Authentication package to the app.
Support for authenticating users is registered in the service container with the xref:Microsoft.Extensions.DependencyInjection.MsalWebAssemblyServiceCollectionExtensions.AddMsalAuthentication%2A extension method provided by the Microsoft.Authentication.WebAssembly.Msal package. This method sets up all of the services required for the app to interact with the Identity Provider (IP).
In the Program file:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
});
The xref:Microsoft.Extensions.DependencyInjection.MsalWebAssemblyServiceCollectionExtensions.AddMsalAuthentication%2A 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 configuration when you register the app.
Configuration is supplied by the wwwroot/appsettings.json file:
{
"AzureAdB2C": {
"Authority": "{AAD B2C INSTANCE}{TENANT DOMAIN}/{SIGN UP OR SIGN IN POLICY}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": false
}
}
In the preceding configuration, the {AAD B2C INSTANCE} includes a trailing slash.
Example:
{
"AzureAdB2C": {
"Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1",
"ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"ValidateAuthority": false
}
}
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 xref:Microsoft.Authentication.WebAssembly.Msal.Models.MsalProviderOptions:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});
Specify additional scopes with AdditionalScopesToConsent:
options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");
[!NOTE] xref:Microsoft.Authentication.WebAssembly.Msal.Models.MsalProviderOptions.AdditionalScopesToConsent%2A isn't able to provision delegated user permissions for Microsoft Graph via the Microsoft Entra ID consent UI when a user first uses an app registered in Microsoft Azure. For more information, see xref:blazor/security/webassembly/graph-api?pivots=graph-sdk-5#defaultaccesstokenscopes-versus-additionalscopestoconsent.
For more information, see the following sections of the Additional scenarios article:
The xref:Microsoft.AspNetCore.Components.Authorization?displayProperty=fullName namespace is made available throughout the app via the _Imports.razor file:
...
@using Microsoft.AspNetCore.Components.Authorization
...