From 145542686b20c74916ca72958676e85fd77f93fe Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Thu, 20 Aug 2026 13:20:58 -0400 Subject: [PATCH 1/9] Patterns for applying authz across Blazor apps --- aspnetcore/blazor/components/render-modes.md | 4 +- .../blazor/globalization-localization.md | 4 +- .../blazor/security/additional-scenarios.md | 169 +++++++++++++++++- aspnetcore/blazor/security/index.md | 6 +- .../blazor/security/webassembly/index.md | 11 +- aspnetcore/mvc/views/razor.md | 2 +- .../security/authorization/introduction.md | 13 +- aspnetcore/security/authorization/simple.md | 2 +- 8 files changed, 191 insertions(+), 20 deletions(-) diff --git a/aspnetcore/blazor/components/render-modes.md b/aspnetcore/blazor/components/render-modes.md index 03e7a77da68e..9fe99ef12128 100644 --- a/aspnetcore/blazor/components/render-modes.md +++ b/aspnetcore/blazor/components/render-modes.md @@ -109,7 +109,7 @@ In the following example, interactive server-side rendering (interactive SSR) is ``` > [!NOTE] -> Blazor templates include a static `using` directive for in the app's `_Imports` file (`Components/_Imports.razor`) for shorter `@rendermode` syntax: +> Blazor templates include a static `using` directive for in the app's imports file (`Components/_Imports.razor`) for shorter `@rendermode` syntax: > > ```razor > @using static Microsoft.AspNetCore.Components.Web.RenderMode @@ -834,7 +834,7 @@ Normally, a component uses the following `@rendermode` directive to [disable pre @rendermode @(new InteractiveServerRenderMode(prerender: false)) ``` -However, consider the following example that creates a shorthand interactive server-side render mode without prerendering via the app's `_Imports` file (`Components/_Imports.razor`): +However, consider the following example that creates a shorthand interactive server-side render mode without prerendering via the app's imports file (`Components/_Imports.razor`): ```csharp public static IComponentRenderMode InteractiveServerWithoutPrerendering { get; } = diff --git a/aspnetcore/blazor/globalization-localization.md b/aspnetcore/blazor/globalization-localization.md index 6af830485c27..276c89892d74 100644 --- a/aspnetcore/blazor/globalization-localization.md +++ b/aspnetcore/blazor/globalization-localization.md @@ -1182,7 +1182,7 @@ The component adopts the following approaches to work for either SSR or CSR comp } ``` -In the `.Client` project's `_Imports` file (`_Imports.razor`), add the namespace for the components in the `Pages` folder, updating the namespace to match your `.Client` project's namespace: +In the `.Client` project's imports file (`_Imports.razor`), add the namespace for the components in the `Pages` folder, updating the namespace to match your `.Client` project's namespace: ```razor @using BlazorSample.Client.Pages @@ -1792,7 +1792,7 @@ To create localization shared resources, adopt the following approach. [!INCLUDE[](~/includes/package-reference.md)] -* Confirm that the namespace is available to the project's Razor components via an entry in the project's `_Imports` file: +* Confirm that the namespace is available to the project's Razor components via an entry in the project's imports file (`_Imports.razor`): ```razor @using Microsoft.Extensions.Localization diff --git a/aspnetcore/blazor/security/additional-scenarios.md b/aspnetcore/blazor/security/additional-scenarios.md index 33faced721c4..eb03a9bc1643 100644 --- a/aspnetcore/blazor/security/additional-scenarios.md +++ b/aspnetcore/blazor/security/additional-scenarios.md @@ -4,7 +4,7 @@ author: guardrex description: Learn how to configure server-side Blazor and Blazor Web Apps for additional security scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 11/11/2025 +ms.date: 08/20/2026 uid: blazor/security/additional-scenarios --- # ASP.NET Core server-side and Blazor Web App additional security scenarios @@ -1369,3 +1369,170 @@ The preceding example's placeholders: In [Duende IdentityServer](https://duendesoftware.com/products/identityserver), tokens are revoked automatically by setting the `CoordinateLifetimeWithUserSession` client configuration property to `true`, which automatically cleans up associated tokens when a session ends. For more information, see [Session Cleanup and Logout (Duende documentation)](https://docs.duendesoftware.com/identityserver/ui/logout/session-cleanup/). Built-in opaque access token support is under consideration for a future release of .NET. For more information, see [Opaque - reference token validation (`dotnet/aspnetcore` #46026)](https://github.com/dotnet/aspnetcore/issues/46026). + +## Patterns to require authorization in a server-side Blazor app + +*For patterns that apply to Blazor WebAssembly apps, see .* + +Server-side Blazor apps (Blazor Web Apps, Blazor Server apps) usually adopt **one** of the following approaches to require authorization: + +* The app sets an authorization fallback policy that requires global authorization and applies the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to resources (for example, Razor components, static assets) that don't require an authenticated user. For more information, see the [Global authorization via a fallback authorization policy](#global-authorization-via-a-fallback-authorization-policy) section. +* Instead of requiring global authorization for resources, the app applies the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) to Razor components that require an authenticated user. For more information, see the [Local authorization via `[Authorize]` attributes](#local-authorization-via-authorize-attributes) section. + +### Global authorization via a fallback authorization policy + +The following demonstration code can be used with the [`BlazorWebAppAuthorization` sample app (`dotnet/AspNetCore.Docs.Samples` GitHub repository)](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/security/authorization/BlazorWebAppAuthorization) ([how to download](xref:index#how-to-download-a-sample)). + +Set the to a policy with in the app's `Program` file, which only applies when there are no authorization attributes or explicit policies set for a given resource: + +```csharp +builder.Services.AddAuthorization(options => +{ + options.FallbackPolicy = options.DefaultPolicy; +}); +``` + +The framework's requires an authenticated user. Unless the app uses a [custom policy provider](xref:security/authorization/custom-authorization-policy-providers) with a custom default policy, assigning the framework's default policy (`options.DefaultPolicy`) is equivalent to using the following code in the app: + +```csharp +builder.Services.AddAuthorization(options => +{ + options.FallbackPolicy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build(); +}); +``` + +At this point, the app requires an authenticated user for any resource where no specific policy is set. + +:::moniker range=">= aspnetcore-9.0" + +Next, an app typically removes protection for static assets in the request processing pipeline of the `Program` file, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user: + +```csharp +app.MapStaticAssets().AllowAnonymous(); +``` + +To selectively allow anonymous access for specific files or paths, apply the to the route pattern inside the endpoint convention lambda of . + +In the following example, the company logo file (`wwwroot/company-logo.png`) is served anonymously when requested: + +```csharp +app.MapStaticAssets() + .Add(endpointBuilder => + { + if (endpointBuilder is RouteEndpointBuilder routeBuilder && + routeBuilder.RoutePattern.RawText?.Contains( + "company-logo.png", StringComparison.OrdinalIgnoreCase) == true) + { + routeBuilder.Metadata.Add(new AllowAnonymousAttribute()); + } + }); +``` + +In the following example, the `/public/` folder path is served anonymously: + +```csharp +app.MapStaticAssets() + .Add(endpointBuilder => + { + if (endpointBuilder is RouteEndpointBuilder routeBuilder && + routeBuilder.RoutePattern.RawText?.Contains( + "/public/", StringComparison.OrdinalIgnoreCase) == true) + { + routeBuilder.Metadata.Add(new AllowAnonymousAttribute()); + } + }); +``` + +:::moniker-end + +:::moniker range="< aspnetcore-9.0" + +To selectively allow anonymous access for specific files or paths, register a separate static files middleware before and are called. A second call to after the authorization pipeline processes the request only serves other static assets if the user is authorized. + +In the following example, the company logo file (`wwwroot/company-logo.png`) is served anonymously when requested: + +```csharp +app.UseStaticFiles(new StaticFileOptions { + FileProvider = new Microsoft.Extensions.FileProviders.SingleFileProvider( + System.IO.Path.Combine(builder.Environment.WebRootPath, "company-logo.png")), + RequestPath = "/" +}); + +app.UseAuthentication(); +app.UseAuthorization(); + +app.UseStaticFiles(); +``` + +In the following example, the `wwwroot/public` folder path is served anonymously: + +```csharp +app.UseStaticFiles(new StaticFileOptions { + FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider( + System.IO.Path.Combine(builder.Environment.WebRootPath, "public")), + RequestPath = "/public" +}); + +app.UseAuthentication(); +app.UseAuthorization(); + +app.UseStaticFiles(); +``` + +:::moniker-end + +Individual components that permit anonymous access set the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute). In the following example, the `Home` component sets the attribute. + +At the top of `Components/Pages/Home.razor`: + +```razor +@page "/" +@using Microsoft.AspNetCore.Authorization +@attribute [AllowAnonymous] +``` + +In the following example, the authentication pages' imports file also receives the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) because authentication pages for signing into/out of the app, access denied, invalid user, and user lockout shouldn't require an authenticated user for access. + +In `Components/Account/Pages/_Imports.razor`: + +```razor +@using Microsoft.AspNetCore.Authorization +@attribute [AllowAnonymous] +``` + +:::moniker range=">= aspnetcore-5.0" + +If the app uses one or more endpoint convention builder instances to provide additional endpoints, such as for Identity components, the builder's method call in the app's `Program` file calls . The following example maps additional Identity endpoints by calling `MapAdditionalIdentityEndpoints`, which returns an : + +```csharp +app.MapAdditionalIdentityEndpoints().AllowAnonymous(); +``` + +> [!NOTE] +> For an example of the preceding `MapAdditionalIdentityEndpoints` method, see [`IdentityComponentsEndpointRouteBuilderExtensions`](https://github.com/dotnet/AspNetCore.Docs.Samples/blob/main/security/authorization/BlazorWebAppAuthorization/Components/Account/IdentityComponentsEndpointRouteBuilderExtensions.cs) in the [`BlazorWebAppAuthorization` sample app (`dotnet/AspNetCore.Docs.Samples` GitHub repository)](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/security/authorization/BlazorWebAppAuthorization). + +:::moniker-end + +### Local authorization via `[Authorize]` attributes + +Apply [`[Authorize]` attributes](xref:blazor/security/index#authorize-attribute) ([API documentation](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute)) to Razor components using ***one*** of the following approaches: + +* In the app's imports file, add an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute). + + `_Imports.razor`: + + ```razor + @using Microsoft.AspNetCore.Authorization + @attribute [Authorize] + ``` + + Imports files can be applied at any level of a folder hierarchy to apply an [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) at and below that folder level. + +* Add the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) to each Razor component that requires authorization under the [`@page`](xref:mvc/views/razor#page) directive: + + ```razor + @using Microsoft.AspNetCore.Authorization + @attribute [Authorize] + ``` diff --git a/aspnetcore/blazor/security/index.md b/aspnetcore/blazor/security/index.md index 994936c084e6..76b9d6ae129e 100644 --- a/aspnetcore/blazor/security/index.md +++ b/aspnetcore/blazor/security/index.md @@ -5,7 +5,7 @@ author: guardrex description: Learn about Blazor authentication and authorization scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 11/11/2025 +ms.date: 08/20/2026 uid: blazor/security/index --- # ASP.NET Core Blazor authentication and authorization @@ -1811,6 +1811,7 @@ PII refers any information relating to an identified or identifiable natural per :::moniker range=">= aspnetcore-6.0" * Server-side and Blazor Web App resources + * [Patterns to require authorization](xref:blazor/security/additional-scenarios#patterns-to-require-authorization-in-a-server-side-blazor-app) * [Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app](/entra/identity-platform/quickstart-v2-aspnet-core-webapp) * [Quickstart: Protect an ASP.NET Core web API with Microsoft identity platform](/entra/identity-platform/quickstart-v2-aspnet-core-web-api) * : Includes guidance on: @@ -1829,12 +1830,14 @@ PII refers any information relating to an identified or identifiable natural per * [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links * * [Opaque (reference) access token support](xref:blazor/security/additional-scenarios#opaque-reference-access-token-support) +* [Patterns to require authorization in a Blazor WebAssembly app](xref:blazor/security/webassembly/index#patterns-to-require-authorization-in-a-blazor-webassembly-app) :::moniker-end :::moniker range="< aspnetcore-6.0" * Server-side Blazor resources + * [Patterns to require authorization](xref:blazor/security/additional-scenarios#patterns-to-require-authorization-in-a-server-side-blazor-app) * [Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app](/entra/identity-platform/quickstart-v2-aspnet-core-webapp) * [Quickstart: Protect an ASP.NET Core web API with Microsoft identity platform](/entra/identity-platform/quickstart-v2-aspnet-core-web-api) * : Includes guidance on: @@ -1852,5 +1855,6 @@ PII refers any information relating to an identified or identifiable natural per * [Build a custom version of the Authentication.MSAL JavaScript library](xref:blazor/security/webassembly/additional-scenarios#build-a-custom-version-of-the-authenticationmsal-javascript-library) * [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links * [Opaque (reference) access token support](xref:blazor/security/additional-scenarios#opaque-reference-access-token-support) +* [Patterns to require authorization in a Blazor WebAssembly app](xref:blazor/security/webassembly/index#patterns-to-require-authorization-in-a-blazor-webassembly-app) :::moniker-end diff --git a/aspnetcore/blazor/security/webassembly/index.md b/aspnetcore/blazor/security/webassembly/index.md index 55ec2a3054da..beee4411aabd 100644 --- a/aspnetcore/blazor/security/webassembly/index.md +++ b/aspnetcore/blazor/security/webassembly/index.md @@ -5,7 +5,7 @@ description: Learn how to secure Blazor WebAssembly apps as single-page applicat monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.custom: sfi-ropc-nochange -ms.date: 11/11/2025 +ms.date: 08/20/2026 uid: blazor/security/webassembly/index --- # Secure ASP.NET Core Blazor WebAssembly @@ -170,9 +170,11 @@ The following authentication scenarios are covered in the .* + +Unlike server-side Blazor apps, setting an to a policy with is **not** supported. Therefore, the only supported pattern for Blazor WebAssembly apps is to apply the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) ([API documentation](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute)) to Razor components using ***one*** of the following approaches: * In the app's imports file, add an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute). @@ -199,9 +201,6 @@ Apply the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribu @attribute [Authorize] ``` -> [!NOTE] -> Setting an to a policy with is **not** supported. - ## Use one identity provider app registration per app :::moniker range=">= aspnetcore-8.0" diff --git a/aspnetcore/mvc/views/razor.md b/aspnetcore/mvc/views/razor.md index 6a46721ab169..a86d1ecdede4 100644 --- a/aspnetcore/mvc/views/razor.md +++ b/aspnetcore/mvc/views/razor.md @@ -766,7 +766,7 @@ In the component definition: ``` > [!NOTE] -> Blazor templates include a static `using` directive for in the app's `_Imports` file (`Components/_Imports.razor`) for shorter `@rendermode` syntax: +> Blazor templates include a static `using` directive for in the app's imports file (`Components/_Imports.razor`) for shorter `@rendermode` syntax: > > ```razor > @using static Microsoft.AspNetCore.Components.Web.RenderMode diff --git a/aspnetcore/security/authorization/introduction.md b/aspnetcore/security/authorization/introduction.md index 2e5d4ad4daef..23b653c23898 100644 --- a/aspnetcore/security/authorization/introduction.md +++ b/aspnetcore/security/authorization/introduction.md @@ -3,10 +3,8 @@ title: Introduction to authorization in ASP.NET Core author: wadepickett description: Learn the basics of authorization and how authorization works in ASP.NET Core apps. ms.author: wpickett -ms.date: 05/15/2026 +ms.date: 08/20/2026 uid: security/authorization/introduction - -# customer intent: As an ASP.NET developer, I want to learn about authorization in ASP.NET Core, so I can use authorization in my apps. --- # Introduction to authorization in ASP.NET Core @@ -22,12 +20,15 @@ ASP.NET Core authorization provides a simple declarative [role](xref:security/au ## Namespaces -Authorization components, including the `AuthorizeAttribute` and `AllowAnonymousAttribute` attributes, are defined in the `Microsoft.AspNetCore.Authorization` namespace. +Authorization components, including the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) and [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) attributes, are defined in the namespace. -Consult the documentation on [simple authorization](xref:security/authorization/simple). +For more information, see . -## Related content +## Additional resources * * * +* Patterns to require authorization in Blazor apps + * [Server-side Blazor apps (Blazor Web Apps, Blazor Server apps)](xref:blazor/security/additional-scenarios#patterns-to-require-authorization-in-a-server-side-blazor-app) + * [Blazor WebAssembly apps](xref:blazor/security/webassembly/index#patterns-to-require-authorization-in-a-blazor-webassembly-app) diff --git a/aspnetcore/security/authorization/simple.md b/aspnetcore/security/authorization/simple.md index 521edf05883b..0868ff4f76a3 100644 --- a/aspnetcore/security/authorization/simple.md +++ b/aspnetcore/security/authorization/simple.md @@ -32,7 +32,7 @@ You can only see this if you're signed in. > [!IMPORTANT] > Only use the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) on `@page` components reached via the Blazor router. Authorization is only performed as an aspect of routing and *not* for child components rendered within a page. To authorize the display of specific parts within a page, use an component instead, which is described in . -The [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) can also be applied to all of the Razor components in a Blazor app or a subset of Razor components in a folder using an `_Imports` file (`_Imports.razor`). Add an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute): +The [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) can also be applied to all of the Razor components in a Blazor app or a subset of Razor components in a folder using an imports file (`_Imports.razor`). Add an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute): ```razor @using Microsoft.AspNetCore.Authorization From 4fa8a065c17f1d3dd9f66aa4570475ec3f2b9576 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 21 Aug 2026 11:38:27 -0400 Subject: [PATCH 2/9] Updates --- .../blazor/security/additional-scenarios.md | 38 +++++++++++-------- aspnetcore/blazor/security/index.md | 2 +- .../blazor/security/webassembly/index.md | 3 +- .../security/authorization/introduction.md | 2 +- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/aspnetcore/blazor/security/additional-scenarios.md b/aspnetcore/blazor/security/additional-scenarios.md index eb03a9bc1643..7e30965fb909 100644 --- a/aspnetcore/blazor/security/additional-scenarios.md +++ b/aspnetcore/blazor/security/additional-scenarios.md @@ -1,13 +1,14 @@ --- -title: ASP.NET Core server-side and Blazor Web App additional security scenarios +title: ASP.NET Core Blazor additional server-side security scenarios +ai-usage: ai-assisted author: guardrex description: Learn how to configure server-side Blazor and Blazor Web Apps for additional security scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 08/20/2026 +ms.date: 08/21/2026 uid: blazor/security/additional-scenarios --- -# ASP.NET Core server-side and Blazor Web App additional security scenarios +# ASP.NET Core Blazor additional server-side security scenarios [!INCLUDE[](~/includes/not-latest-version.md)] @@ -1374,10 +1375,10 @@ Built-in opaque access token support is under consideration for a future release *For patterns that apply to Blazor WebAssembly apps, see .* -Server-side Blazor apps (Blazor Web Apps, Blazor Server apps) usually adopt **one** of the following approaches to require authorization: +Server-side Blazor apps (Blazor Web Apps, Blazor Server apps) usually adopt **either** of the following approaches to require authorization: -* The app sets an authorization fallback policy that requires global authorization and applies the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to resources (for example, Razor components, static assets) that don't require an authenticated user. For more information, see the [Global authorization via a fallback authorization policy](#global-authorization-via-a-fallback-authorization-policy) section. -* Instead of requiring global authorization for resources, the app applies the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) to Razor components that require an authenticated user. For more information, see the [Local authorization via `[Authorize]` attributes](#local-authorization-via-authorize-attributes) section. +* The app sets an authorization fallback policy that requires authorization globally across the app and applies the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to resources (for example, Razor components, static assets) that don't require an authenticated user. For more information, see the [Global authorization via a fallback authorization policy](#global-authorization-via-a-fallback-authorization-policy) section. +* Instead of requiring global authorization for resources, the app applies the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) to resources that require an authorized user. For more information, see the [Local authorization via `[Authorize]` attributes](#local-authorization-via-authorize-attributes) section. ### Global authorization via a fallback authorization policy @@ -1392,7 +1393,7 @@ builder.Services.AddAuthorization(options => }); ``` -The framework's requires an authenticated user. Unless the app uses a [custom policy provider](xref:security/authorization/custom-authorization-policy-providers) with a custom default policy, assigning the framework's default policy (`options.DefaultPolicy`) is equivalent to using the following code in the app: +The framework's requires an authenticated user. Unless the app uses a [custom policy provider](xref:security/authorization/custom-authorization-policy-providers) with a custom default policy, assigning the framework's default policy (`options.DefaultPolicy`), as shown in the preceding example, is equivalent to using the following code: ```csharp builder.Services.AddAuthorization(options => @@ -1430,7 +1431,7 @@ app.MapStaticAssets() }); ``` -In the following example, the `/public/` folder path is served anonymously: +Usually, it's more convenient to place static assets for anonymous requests into a single folder. In the following example, endpoint routes with the `/public/` path segment are served anonymously: ```csharp app.MapStaticAssets() @@ -1449,7 +1450,7 @@ app.MapStaticAssets() :::moniker range="< aspnetcore-9.0" -To selectively allow anonymous access for specific files or paths, register a separate static files middleware before and are called. A second call to after the authorization pipeline processes the request only serves other static assets if the user is authorized. +To selectively allow anonymous access for specific files or paths, register a separate static files middleware before and are called. A second call to after authorization pipeline processing only serves other static assets if the user is authorized. In the following example, the company logo file (`wwwroot/company-logo.png`) is served anonymously when requested: @@ -1466,7 +1467,7 @@ app.UseAuthorization(); app.UseStaticFiles(); ``` -In the following example, the `wwwroot/public` folder path is served anonymously: +In the following example, static assets in the app's `wwwroot/public` folder are served anonymously: ```csharp app.UseStaticFiles(new StaticFileOptions { @@ -1483,7 +1484,10 @@ app.UseStaticFiles(); :::moniker-end -Individual components that permit anonymous access set the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute). In the following example, the `Home` component sets the attribute. +Use an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to permit anonymous access to individual components. In the following example, the `Home` component sets the attribute. + +> [!NOTE] +> The [`@using`](xref:mvc/views/razor#using) directive for the namespace in the following example can be applied broadly to the app's components by placing it into the app's imports file (`_Imports.razor`) instead of in individual components. At the top of `Components/Pages/Home.razor`: @@ -1493,7 +1497,7 @@ At the top of `Components/Pages/Home.razor`: @attribute [AllowAnonymous] ``` -In the following example, the authentication pages' imports file also receives the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) because authentication pages for signing into/out of the app, access denied, invalid user, and user lockout shouldn't require an authenticated user for access. +Often, it's more convenient to apply authorization to an entire folder of components. In the following example, a user account pages' imports file sets the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute), so users can anonymously reach the app's sign-in, sign-out, access denied, and invalid user pages. In `Components/Account/Pages/_Imports.razor`: @@ -1504,7 +1508,7 @@ In `Components/Account/Pages/_Imports.razor`: :::moniker range=">= aspnetcore-5.0" -If the app uses one or more endpoint convention builder instances to provide additional endpoints, such as for Identity components, the builder's method call in the app's `Program` file calls . The following example maps additional Identity endpoints by calling `MapAdditionalIdentityEndpoints`, which returns an : +If the app uses one or more endpoint convention builder instances to provide additional endpoints, such as for Identity components, the endpoint builder's method call in the app's `Program` file chains a call to . The following example maps additional Identity endpoints by calling `MapAdditionalIdentityEndpoints`, which returns an : ```csharp app.MapAdditionalIdentityEndpoints().AllowAnonymous(); @@ -1517,7 +1521,7 @@ app.MapAdditionalIdentityEndpoints().AllowAnonymous(); ### Local authorization via `[Authorize]` attributes -Apply [`[Authorize]` attributes](xref:blazor/security/index#authorize-attribute) ([API documentation](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute)) to Razor components using ***one*** of the following approaches: +Apply [`[Authorize]` attributes](xref:blazor/security/index#authorize-attribute) ([API documentation](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute)) to Razor components using ***either*** of the following approaches: * In the app's imports file, add an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute). @@ -1528,11 +1532,13 @@ Apply [`[Authorize]` attributes](xref:blazor/security/index#authorize-attribute) @attribute [Authorize] ``` - Imports files can be applied at any level of a folder hierarchy to apply an [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) at and below that folder level. + Imports files can be applied at any level of a folder hierarchy to apply an [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) for that folder's components and its subfolders. -* Add the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) to each Razor component that requires authorization under the [`@page`](xref:mvc/views/razor#page) directive: +* Add the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) to each Razor component that requires authorization under the [`@page`](xref:mvc/views/razor#page) directive with an [`@using`](xref:mvc/views/razor#using) directive for the namespace: ```razor @using Microsoft.AspNetCore.Authorization @attribute [Authorize] ``` + + The [`@using`](xref:mvc/views/razor#using) directive for the namespace in the preceding example can be applied broadly to the app's components by placing it into the app's imports file (`_Imports.razor`) instead of in individual components. diff --git a/aspnetcore/blazor/security/index.md b/aspnetcore/blazor/security/index.md index 76b9d6ae129e..52956eb6d5fb 100644 --- a/aspnetcore/blazor/security/index.md +++ b/aspnetcore/blazor/security/index.md @@ -5,7 +5,7 @@ author: guardrex description: Learn about Blazor authentication and authorization scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 08/20/2026 +ms.date: 08/21/2026 uid: blazor/security/index --- # ASP.NET Core Blazor authentication and authorization diff --git a/aspnetcore/blazor/security/webassembly/index.md b/aspnetcore/blazor/security/webassembly/index.md index beee4411aabd..51fb9657ffd8 100644 --- a/aspnetcore/blazor/security/webassembly/index.md +++ b/aspnetcore/blazor/security/webassembly/index.md @@ -1,11 +1,12 @@ --- title: Secure ASP.NET Core Blazor WebAssembly +ai-usage: ai-assisted author: guardrex description: Learn how to secure Blazor WebAssembly apps as single-page applications (SPAs). monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.custom: sfi-ropc-nochange -ms.date: 08/20/2026 +ms.date: 08/21/2026 uid: blazor/security/webassembly/index --- # Secure ASP.NET Core Blazor WebAssembly diff --git a/aspnetcore/security/authorization/introduction.md b/aspnetcore/security/authorization/introduction.md index 23b653c23898..5b7c9c4c88bf 100644 --- a/aspnetcore/security/authorization/introduction.md +++ b/aspnetcore/security/authorization/introduction.md @@ -3,7 +3,7 @@ title: Introduction to authorization in ASP.NET Core author: wadepickett description: Learn the basics of authorization and how authorization works in ASP.NET Core apps. ms.author: wpickett -ms.date: 08/20/2026 +ms.date: 08/21/2026 uid: security/authorization/introduction --- # Introduction to authorization in ASP.NET Core From abe1690fe709ddac469549b923717360694a92d2 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 21 Aug 2026 11:54:33 -0400 Subject: [PATCH 3/9] Updates --- aspnetcore/blazor/components/render-modes.md | 4 ++-- aspnetcore/blazor/globalization-localization.md | 4 ++-- aspnetcore/blazor/security/additional-scenarios.md | 4 ++-- aspnetcore/mvc/views/razor.md | 2 +- aspnetcore/security/authorization/introduction.md | 2 +- aspnetcore/security/authorization/simple.md | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/aspnetcore/blazor/components/render-modes.md b/aspnetcore/blazor/components/render-modes.md index 9fe99ef12128..03e7a77da68e 100644 --- a/aspnetcore/blazor/components/render-modes.md +++ b/aspnetcore/blazor/components/render-modes.md @@ -109,7 +109,7 @@ In the following example, interactive server-side rendering (interactive SSR) is ``` > [!NOTE] -> Blazor templates include a static `using` directive for in the app's imports file (`Components/_Imports.razor`) for shorter `@rendermode` syntax: +> Blazor templates include a static `using` directive for in the app's `_Imports` file (`Components/_Imports.razor`) for shorter `@rendermode` syntax: > > ```razor > @using static Microsoft.AspNetCore.Components.Web.RenderMode @@ -834,7 +834,7 @@ Normally, a component uses the following `@rendermode` directive to [disable pre @rendermode @(new InteractiveServerRenderMode(prerender: false)) ``` -However, consider the following example that creates a shorthand interactive server-side render mode without prerendering via the app's imports file (`Components/_Imports.razor`): +However, consider the following example that creates a shorthand interactive server-side render mode without prerendering via the app's `_Imports` file (`Components/_Imports.razor`): ```csharp public static IComponentRenderMode InteractiveServerWithoutPrerendering { get; } = diff --git a/aspnetcore/blazor/globalization-localization.md b/aspnetcore/blazor/globalization-localization.md index 276c89892d74..6af830485c27 100644 --- a/aspnetcore/blazor/globalization-localization.md +++ b/aspnetcore/blazor/globalization-localization.md @@ -1182,7 +1182,7 @@ The component adopts the following approaches to work for either SSR or CSR comp } ``` -In the `.Client` project's imports file (`_Imports.razor`), add the namespace for the components in the `Pages` folder, updating the namespace to match your `.Client` project's namespace: +In the `.Client` project's `_Imports` file (`_Imports.razor`), add the namespace for the components in the `Pages` folder, updating the namespace to match your `.Client` project's namespace: ```razor @using BlazorSample.Client.Pages @@ -1792,7 +1792,7 @@ To create localization shared resources, adopt the following approach. [!INCLUDE[](~/includes/package-reference.md)] -* Confirm that the namespace is available to the project's Razor components via an entry in the project's imports file (`_Imports.razor`): +* Confirm that the namespace is available to the project's Razor components via an entry in the project's `_Imports` file: ```razor @using Microsoft.Extensions.Localization diff --git a/aspnetcore/blazor/security/additional-scenarios.md b/aspnetcore/blazor/security/additional-scenarios.md index 7e30965fb909..d42c7c165b1e 100644 --- a/aspnetcore/blazor/security/additional-scenarios.md +++ b/aspnetcore/blazor/security/additional-scenarios.md @@ -8,7 +8,7 @@ ms.author: wpickett ms.date: 08/21/2026 uid: blazor/security/additional-scenarios --- -# ASP.NET Core Blazor additional server-side security scenarios +# ASP.NET Core Blazor additional server-side security scenarios [!INCLUDE[](~/includes/not-latest-version.md)] @@ -1456,7 +1456,7 @@ In the following example, the company logo file (`wwwroot/company-logo.png`) is ```csharp app.UseStaticFiles(new StaticFileOptions { - FileProvider = new Microsoft.Extensions.FileProviders.SingleFileProvider( + FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider( System.IO.Path.Combine(builder.Environment.WebRootPath, "company-logo.png")), RequestPath = "/" }); diff --git a/aspnetcore/mvc/views/razor.md b/aspnetcore/mvc/views/razor.md index a86d1ecdede4..6a46721ab169 100644 --- a/aspnetcore/mvc/views/razor.md +++ b/aspnetcore/mvc/views/razor.md @@ -766,7 +766,7 @@ In the component definition: ``` > [!NOTE] -> Blazor templates include a static `using` directive for in the app's imports file (`Components/_Imports.razor`) for shorter `@rendermode` syntax: +> Blazor templates include a static `using` directive for in the app's `_Imports` file (`Components/_Imports.razor`) for shorter `@rendermode` syntax: > > ```razor > @using static Microsoft.AspNetCore.Components.Web.RenderMode diff --git a/aspnetcore/security/authorization/introduction.md b/aspnetcore/security/authorization/introduction.md index 5b7c9c4c88bf..c2400823e293 100644 --- a/aspnetcore/security/authorization/introduction.md +++ b/aspnetcore/security/authorization/introduction.md @@ -20,7 +20,7 @@ ASP.NET Core authorization provides a simple declarative [role](xref:security/au ## Namespaces -Authorization components, including the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) and [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) attributes, are defined in the namespace. +Authorization components, including the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) and [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute), are defined in the namespace. For more information, see . diff --git a/aspnetcore/security/authorization/simple.md b/aspnetcore/security/authorization/simple.md index 0868ff4f76a3..521edf05883b 100644 --- a/aspnetcore/security/authorization/simple.md +++ b/aspnetcore/security/authorization/simple.md @@ -32,7 +32,7 @@ You can only see this if you're signed in. > [!IMPORTANT] > Only use the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) on `@page` components reached via the Blazor router. Authorization is only performed as an aspect of routing and *not* for child components rendered within a page. To authorize the display of specific parts within a page, use an component instead, which is described in . -The [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) can also be applied to all of the Razor components in a Blazor app or a subset of Razor components in a folder using an imports file (`_Imports.razor`). Add an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute): +The [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) can also be applied to all of the Razor components in a Blazor app or a subset of Razor components in a folder using an `_Imports` file (`_Imports.razor`). Add an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute): ```razor @using Microsoft.AspNetCore.Authorization From e57779c5b7bc1518f938380ec6883a13a728bba7 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 21 Aug 2026 13:39:28 -0400 Subject: [PATCH 4/9] Updates --- .../blazor/fundamentals/static-files.md | 6 +- .../blazor/security/additional-scenarios.md | 95 ++++++++++++++++++- 2 files changed, 94 insertions(+), 7 deletions(-) diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index 4f4e92e694b1..a0844896178c 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -4,7 +4,7 @@ author: guardrex description: Learn how to configure and manage static files for Blazor apps. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 11/11/2025 +ms.date: 08/21/2026 uid: blazor/fundamentals/static-files --- # ASP.NET Core Blazor static files @@ -505,7 +505,7 @@ To create additional file mappings with a to execute a custom static file middleware: +* You can avoid interfering with serving `_framework/blazor.server.js` by using to execute a custom static files middleware: ```csharp app.MapWhen(ctx => !ctx.Request.Path @@ -538,7 +538,7 @@ Add the following `using` statement to the top of the server project's `Program` using Microsoft.Extensions.FileProviders; ``` -In the server project's `Program` file ***before*** the call to , add the following code: +In the server project's `Program` file ***before*** any calls to and , add the following code: ```csharp var secondaryProvider = new PhysicalFileProvider( diff --git a/aspnetcore/blazor/security/additional-scenarios.md b/aspnetcore/blazor/security/additional-scenarios.md index d42c7c165b1e..1ead6d8c5911 100644 --- a/aspnetcore/blazor/security/additional-scenarios.md +++ b/aspnetcore/blazor/security/additional-scenarios.md @@ -1384,7 +1384,9 @@ Server-side Blazor apps (Blazor Web Apps, Blazor Server apps) usually adopt **ei The following demonstration code can be used with the [`BlazorWebAppAuthorization` sample app (`dotnet/AspNetCore.Docs.Samples` GitHub repository)](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/security/authorization/BlazorWebAppAuthorization) ([how to download](xref:index#how-to-download-a-sample)). -Set the to a policy with in the app's `Program` file, which only applies when there are no authorization attributes or explicit policies set for a given resource: +Set the to a policy with , which only applies when there are no authorization attributes or explicit policies set for a given resource: + +:::moniker range=">= aspnetcore-6.0" ```csharp builder.Services.AddAuthorization(options => @@ -1393,8 +1395,23 @@ builder.Services.AddAuthorization(options => }); ``` +:::moniker-end + +:::moniker range="< aspnetcore-6.0" + +```csharp +services.AddAuthorization(options => +{ + options.FallbackPolicy = options.DefaultPolicy; +}); +``` + +:::moniker-end + The framework's requires an authenticated user. Unless the app uses a [custom policy provider](xref:security/authorization/custom-authorization-policy-providers) with a custom default policy, assigning the framework's default policy (`options.DefaultPolicy`), as shown in the preceding example, is equivalent to using the following code: +:::moniker range=">= aspnetcore-6.0" + ```csharp builder.Services.AddAuthorization(options => { @@ -1404,11 +1421,26 @@ builder.Services.AddAuthorization(options => }); ``` +:::moniker-end + +:::moniker range="< aspnetcore-6.0" + +```csharp +services.AddAuthorization(options => +{ + options.FallbackPolicy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build(); +}); +``` + +:::moniker-end + At this point, the app requires an authenticated user for any resource where no specific policy is set. :::moniker range=">= aspnetcore-9.0" -Next, an app typically removes protection for static assets in the request processing pipeline of the `Program` file, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user: +Next, an app typically removes protection for static assets in the request processing pipeline, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user: ```csharp app.MapStaticAssets().AllowAnonymous(); @@ -1416,7 +1448,10 @@ app.MapStaticAssets().AllowAnonymous(); To selectively allow anonymous access for specific files or paths, apply the to the route pattern inside the endpoint convention lambda of . -In the following example, the company logo file (`wwwroot/company-logo.png`) is served anonymously when requested: +> [!IMPORTANT] +> When only authorizing specific endpoints for anonymous access, the [Blazor script](xref:blazor/project-structure#location-of-the-blazor-script) and other Blazor static assets, such as stylesheets, scripts, and modules, must be taken into consideration. If anonymous Razor component pages require the assets to render and function correctly, the assets must be made available anonymously as well because they're requested separately via Map Static Assets routing endpoint conventions or static files middleware. + +In the following example, a company logo image (`wwwroot/company-logo.png`) is served anonymously when requested: ```csharp app.MapStaticAssets() @@ -1446,12 +1481,46 @@ app.MapStaticAssets() }); ``` +The next example demonstrates anonymously serving the uncompressed Blazor script (`_framework/blazor.web.{FINGERPRINT}.js`, where the `{FINGERPRINT}` placeholder is the file's fingerprint): + +```csharp +// using System.Text.RegularExpressions; + +var regex = new Regex( + @"^_framework/blazor\.web\.[a-z0-9]{10}\.js$", RegexOptions.Compiled); + +app.MapStaticAssets() + .Add(endpointBuilder => + { + if (endpointBuilder is RouteEndpointBuilder routeBuilder && + regex.IsMatch(routeBuilder.RoutePattern.RawText ?? string.Empty)) + { + routeBuilder.Metadata.Add(new AllowAnonymousAttribute()); + } + }); +``` + +> [!NOTE] +> For a typical Blazor Web App, setting up explicit anonymous asset loading typically requires mapping assets for several dozen uncompressed and compressed, sometimes fingerprinted, assets. For this reason, we recommend avoiding explicit anonymous asset mapping in favor of calling `app.MapStaticAssets().AllowAnonymous();` to serve all of the app's static assets anonymously when the security specification of the app permits it. + :::moniker-end :::moniker range="< aspnetcore-9.0" +Next, an app typically removes protection for static assets in the request processing pipeline, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user. Place the call to ***before*** and are called: + +```csharp +app.UseStaticFiles(); + +app.UseAuthentication(); +app.UseAuthorization(); +``` + To selectively allow anonymous access for specific files or paths, register a separate static files middleware before and are called. A second call to after authorization pipeline processing only serves other static assets if the user is authorized. +> [!IMPORTANT] +> When only authorizing specific endpoints for anonymous access, the [Blazor script](xref:blazor/project-structure#location-of-the-blazor-script) and other Blazor static assets, such as stylesheets, scripts, and modules, must be taken into consideration. If anonymous Razor component pages require the assets to render and function correctly, the assets must be made available anonymously as well because they're requested separately via static files middleware. + In the following example, the company logo file (`wwwroot/company-logo.png`) is served anonymously when requested: ```csharp @@ -1482,6 +1551,24 @@ app.UseAuthorization(); app.UseStaticFiles(); ``` +The next example demonstrates anonymously serving the Blazor server script (`_framework/blazor.server.js`): + +```csharp +app.UseStaticFiles(new StaticFileOptions { + FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider( + System.IO.Path.Combine(builder.Environment.WebRootPath, "_framework/blazor.server.js")), + RequestPath = "/public" +}); + +app.UseAuthentication(); +app.UseAuthorization(); + +app.UseStaticFiles(); +``` + +> [!NOTE] +> For a typical Blazor app, setting up explicit anonymous asset loading typically requires mapping assets for several dozen uncompressed and compressed assets. For this reason, we recommend avoiding explicit anonymous asset mapping in favor of calling before the authorization pipeline methods are called to serve all of the app's static assets anonymously when the security specification of the app permits it. + :::moniker-end Use an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to permit anonymous access to individual components. In the following example, the `Home` component sets the attribute. @@ -1508,7 +1595,7 @@ In `Components/Account/Pages/_Imports.razor`: :::moniker range=">= aspnetcore-5.0" -If the app uses one or more endpoint convention builder instances to provide additional endpoints, such as for Identity components, the endpoint builder's method call in the app's `Program` file chains a call to . The following example maps additional Identity endpoints by calling `MapAdditionalIdentityEndpoints`, which returns an : +If the app uses one or more endpoint convention builder instances to provide additional endpoints, such as for Identity components, the endpoint builder's method call chains a call to . The following example maps additional Identity endpoints by calling `MapAdditionalIdentityEndpoints`, which returns an : ```csharp app.MapAdditionalIdentityEndpoints().AllowAnonymous(); From ff996c5e58051d97e684d41ca4419c60548e9f25 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 21 Aug 2026 14:51:48 -0400 Subject: [PATCH 5/9] Updates --- .../blazor/security/additional-scenarios.md | 59 +++---------------- 1 file changed, 7 insertions(+), 52 deletions(-) diff --git a/aspnetcore/blazor/security/additional-scenarios.md b/aspnetcore/blazor/security/additional-scenarios.md index 1ead6d8c5911..e33d1828cc3b 100644 --- a/aspnetcore/blazor/security/additional-scenarios.md +++ b/aspnetcore/blazor/security/additional-scenarios.md @@ -1436,37 +1436,22 @@ services.AddAuthorization(options => :::moniker-end -At this point, the app requires an authenticated user for any resource where no specific policy is set. +The app requires an authenticated user for any resource where no specific policy is set. :::moniker range=">= aspnetcore-9.0" -Next, an app typically removes protection for static assets in the request processing pipeline, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user: +An app typically removes protection for static assets in the request processing pipeline, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user: ```csharp app.MapStaticAssets().AllowAnonymous(); ``` -To selectively allow anonymous access for specific files or paths, apply the to the route pattern inside the endpoint convention lambda of . +To selectively allow anonymous access for specific paths, apply the to the route pattern inside the endpoint convention lambda of . > [!IMPORTANT] > When only authorizing specific endpoints for anonymous access, the [Blazor script](xref:blazor/project-structure#location-of-the-blazor-script) and other Blazor static assets, such as stylesheets, scripts, and modules, must be taken into consideration. If anonymous Razor component pages require the assets to render and function correctly, the assets must be made available anonymously as well because they're requested separately via Map Static Assets routing endpoint conventions or static files middleware. -In the following example, a company logo image (`wwwroot/company-logo.png`) is served anonymously when requested: - -```csharp -app.MapStaticAssets() - .Add(endpointBuilder => - { - if (endpointBuilder is RouteEndpointBuilder routeBuilder && - routeBuilder.RoutePattern.RawText?.Contains( - "company-logo.png", StringComparison.OrdinalIgnoreCase) == true) - { - routeBuilder.Metadata.Add(new AllowAnonymousAttribute()); - } - }); -``` - -Usually, it's more convenient to place static assets for anonymous requests into a single folder. In the following example, endpoint routes with the `/public/` path segment are served anonymously: +Place static assets for anonymous access into a single folder. In the following example, endpoint routes with the `/public/` path segment are served anonymously: ```csharp app.MapStaticAssets() @@ -1507,7 +1492,7 @@ app.MapStaticAssets() :::moniker range="< aspnetcore-9.0" -Next, an app typically removes protection for static assets in the request processing pipeline, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user. Place the call to ***before*** and are called: +An app typically removes protection for static assets in the request processing pipeline, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user. Place the call to ***before*** and are called: ```csharp app.UseStaticFiles(); @@ -1516,26 +1501,11 @@ app.UseAuthentication(); app.UseAuthorization(); ``` -To selectively allow anonymous access for specific files or paths, register a separate static files middleware before and are called. A second call to after authorization pipeline processing only serves other static assets if the user is authorized. +To selectively allow anonymous access for specific paths, register a separate static files middleware before and are called. A second call to after authorization pipeline processing only serves other static assets if the user is authorized. > [!IMPORTANT] > When only authorizing specific endpoints for anonymous access, the [Blazor script](xref:blazor/project-structure#location-of-the-blazor-script) and other Blazor static assets, such as stylesheets, scripts, and modules, must be taken into consideration. If anonymous Razor component pages require the assets to render and function correctly, the assets must be made available anonymously as well because they're requested separately via static files middleware. -In the following example, the company logo file (`wwwroot/company-logo.png`) is served anonymously when requested: - -```csharp -app.UseStaticFiles(new StaticFileOptions { - FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider( - System.IO.Path.Combine(builder.Environment.WebRootPath, "company-logo.png")), - RequestPath = "/" -}); - -app.UseAuthentication(); -app.UseAuthorization(); - -app.UseStaticFiles(); -``` - In the following example, static assets in the app's `wwwroot/public` folder are served anonymously: ```csharp @@ -1551,23 +1521,8 @@ app.UseAuthorization(); app.UseStaticFiles(); ``` -The next example demonstrates anonymously serving the Blazor server script (`_framework/blazor.server.js`): - -```csharp -app.UseStaticFiles(new StaticFileOptions { - FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider( - System.IO.Path.Combine(builder.Environment.WebRootPath, "_framework/blazor.server.js")), - RequestPath = "/public" -}); - -app.UseAuthentication(); -app.UseAuthorization(); - -app.UseStaticFiles(); -``` - > [!NOTE] -> For a typical Blazor app, setting up explicit anonymous asset loading typically requires mapping assets for several dozen uncompressed and compressed assets. For this reason, we recommend avoiding explicit anonymous asset mapping in favor of calling before the authorization pipeline methods are called to serve all of the app's static assets anonymously when the security specification of the app permits it. +> In a typical Blazor app, setting up explicit anonymous asset loading requires mapping assets for several dozen uncompressed and compressed assets. For this reason, we recommend avoiding explicit anonymous asset mapping in favor of calling before the authorization pipeline methods are called to serve all of the app's static assets anonymously when the security specification of the app permits it. :::moniker-end From 41dc3ea20bee9a27c956a97fa69cc7de52371f3a Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 24 Aug 2026 15:41:20 -0400 Subject: [PATCH 6/9] Updates --- .../blazor/fundamentals/static-files.md | 2 +- .../blazor/security/additional-scenarios.md | 25 ++++++------------- .../blazor/security/webassembly/index.md | 2 +- .../security/authorization/introduction.md | 1 + 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index a0844896178c..ac72923a3049 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -4,7 +4,7 @@ author: guardrex description: Learn how to configure and manage static files for Blazor apps. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 08/21/2026 +ms.date: 08/24/2026 uid: blazor/fundamentals/static-files --- # ASP.NET Core Blazor static files diff --git a/aspnetcore/blazor/security/additional-scenarios.md b/aspnetcore/blazor/security/additional-scenarios.md index e33d1828cc3b..f80141a148b9 100644 --- a/aspnetcore/blazor/security/additional-scenarios.md +++ b/aspnetcore/blazor/security/additional-scenarios.md @@ -5,7 +5,7 @@ author: guardrex description: Learn how to configure server-side Blazor and Blazor Web Apps for additional security scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 08/21/2026 +ms.date: 08/24/2026 uid: blazor/security/additional-scenarios --- # ASP.NET Core Blazor additional server-side security scenarios @@ -1440,16 +1440,16 @@ The app requires an authenticated user for any resource where no specific policy :::moniker range=">= aspnetcore-9.0" -An app typically removes protection for static assets in the request processing pipeline, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user: +If the app's security specification doesn't call for protecting static assets, call on : ```csharp app.MapStaticAssets().AllowAnonymous(); ``` -To selectively allow anonymous access for specific paths, apply the to the route pattern inside the endpoint convention lambda of . +To alternatively allow anonymous access for specific paths, apply the to the route pattern inside the endpoint convention lambda of . > [!IMPORTANT] -> When only authorizing specific endpoints for anonymous access, the [Blazor script](xref:blazor/project-structure#location-of-the-blazor-script) and other Blazor static assets, such as stylesheets, scripts, and modules, must be taken into consideration. If anonymous Razor component pages require the assets to render and function correctly, the assets must be made available anonymously as well because they're requested separately via Map Static Assets routing endpoint conventions or static files middleware. +> When only authorizing specific endpoints for anonymous access, the [Blazor script](xref:blazor/project-structure#location-of-the-blazor-script) and other Blazor static assets, such as stylesheets, scripts, and modules, must be taken into consideration. If public Razor component pages require the assets to render and function correctly, the assets must be made available anonymously as well because they're requested separately via Map Static Assets routing endpoint conventions or static files middleware. Place static assets for anonymous access into a single folder. In the following example, endpoint routes with the `/public/` path segment are served anonymously: @@ -1485,14 +1485,11 @@ app.MapStaticAssets() }); ``` -> [!NOTE] -> For a typical Blazor Web App, setting up explicit anonymous asset loading typically requires mapping assets for several dozen uncompressed and compressed, sometimes fingerprinted, assets. For this reason, we recommend avoiding explicit anonymous asset mapping in favor of calling `app.MapStaticAssets().AllowAnonymous();` to serve all of the app's static assets anonymously when the security specification of the app permits it. - :::moniker-end :::moniker range="< aspnetcore-9.0" -An app typically removes protection for static assets in the request processing pipeline, which allows static assets to load for unauthenticated users accessing endpoints (for example, Razor component pages) that don't require an authenticated user. Place the call to ***before*** and are called: +If the app's security specification doesn't call for protecting static assets, place the call to ***before*** and : ```csharp app.UseStaticFiles(); @@ -1501,10 +1498,10 @@ app.UseAuthentication(); app.UseAuthorization(); ``` -To selectively allow anonymous access for specific paths, register a separate static files middleware before and are called. A second call to after authorization pipeline processing only serves other static assets if the user is authorized. +To alternatively allow anonymous access for specific paths, register a separate static files middleware before and are called. A second call to after authorization pipeline processing only serves other static assets if the user is authorized. > [!IMPORTANT] -> When only authorizing specific endpoints for anonymous access, the [Blazor script](xref:blazor/project-structure#location-of-the-blazor-script) and other Blazor static assets, such as stylesheets, scripts, and modules, must be taken into consideration. If anonymous Razor component pages require the assets to render and function correctly, the assets must be made available anonymously as well because they're requested separately via static files middleware. +> When only authorizing specific endpoints for anonymous access, the [Blazor script](xref:blazor/project-structure#location-of-the-blazor-script) and other Blazor static assets, such as stylesheets, scripts, and modules, must be taken into consideration. If public Razor component pages require the assets to render and function correctly, the assets must be made available anonymously as well because they're requested separately via static files middleware. In the following example, static assets in the app's `wwwroot/public` folder are served anonymously: @@ -1521,16 +1518,10 @@ app.UseAuthorization(); app.UseStaticFiles(); ``` -> [!NOTE] -> In a typical Blazor app, setting up explicit anonymous asset loading requires mapping assets for several dozen uncompressed and compressed assets. For this reason, we recommend avoiding explicit anonymous asset mapping in favor of calling before the authorization pipeline methods are called to serve all of the app's static assets anonymously when the security specification of the app permits it. - :::moniker-end Use an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to permit anonymous access to individual components. In the following example, the `Home` component sets the attribute. -> [!NOTE] -> The [`@using`](xref:mvc/views/razor#using) directive for the namespace in the following example can be applied broadly to the app's components by placing it into the app's imports file (`_Imports.razor`) instead of in individual components. - At the top of `Components/Pages/Home.razor`: ```razor @@ -1539,7 +1530,7 @@ At the top of `Components/Pages/Home.razor`: @attribute [AllowAnonymous] ``` -Often, it's more convenient to apply authorization to an entire folder of components. In the following example, a user account pages' imports file sets the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute), so users can anonymously reach the app's sign-in, sign-out, access denied, and invalid user pages. +Often, it's convenient to apply authorization to an entire folder of components. In the following example, a user account pages' imports file sets the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute), so users can anonymously reach the app's sign-in, sign-out, access denied, and invalid user pages in the `Components/Account/Pages` folder. In `Components/Account/Pages/_Imports.razor`: diff --git a/aspnetcore/blazor/security/webassembly/index.md b/aspnetcore/blazor/security/webassembly/index.md index 51fb9657ffd8..89e822c94320 100644 --- a/aspnetcore/blazor/security/webassembly/index.md +++ b/aspnetcore/blazor/security/webassembly/index.md @@ -6,7 +6,7 @@ description: Learn how to secure Blazor WebAssembly apps as single-page applicat monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.custom: sfi-ropc-nochange -ms.date: 08/21/2026 +ms.date: 08/24/2026 uid: blazor/security/webassembly/index --- # Secure ASP.NET Core Blazor WebAssembly diff --git a/aspnetcore/security/authorization/introduction.md b/aspnetcore/security/authorization/introduction.md index c2400823e293..0247568eeca0 100644 --- a/aspnetcore/security/authorization/introduction.md +++ b/aspnetcore/security/authorization/introduction.md @@ -1,5 +1,6 @@ --- title: Introduction to authorization in ASP.NET Core +ai-usage: ai-assisted author: wadepickett description: Learn the basics of authorization and how authorization works in ASP.NET Core apps. ms.author: wpickett From 2cb1e1a8a671259102a3f72d11882b38c87ba604 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 24 Aug 2026 15:51:18 -0400 Subject: [PATCH 7/9] Updates --- aspnetcore/blazor/fundamentals/static-files.md | 1 + aspnetcore/blazor/security/index.md | 2 +- aspnetcore/security/authorization/introduction.md | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index ac72923a3049..51f85a82eab2 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -1,5 +1,6 @@ --- title: ASP.NET Core Blazor static files +ai-usage: ai-assisted author: guardrex description: Learn how to configure and manage static files for Blazor apps. monikerRange: '>= aspnetcore-3.1' diff --git a/aspnetcore/blazor/security/index.md b/aspnetcore/blazor/security/index.md index 52956eb6d5fb..f59e292d2d46 100644 --- a/aspnetcore/blazor/security/index.md +++ b/aspnetcore/blazor/security/index.md @@ -5,7 +5,7 @@ author: guardrex description: Learn about Blazor authentication and authorization scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 08/21/2026 +ms.date: 08/24/2026 uid: blazor/security/index --- # ASP.NET Core Blazor authentication and authorization diff --git a/aspnetcore/security/authorization/introduction.md b/aspnetcore/security/authorization/introduction.md index 0247568eeca0..03f77d4a75d6 100644 --- a/aspnetcore/security/authorization/introduction.md +++ b/aspnetcore/security/authorization/introduction.md @@ -4,7 +4,7 @@ ai-usage: ai-assisted author: wadepickett description: Learn the basics of authorization and how authorization works in ASP.NET Core apps. ms.author: wpickett -ms.date: 08/21/2026 +ms.date: 08/24/2026 uid: security/authorization/introduction --- # Introduction to authorization in ASP.NET Core From c16649226159ab90f32d6f2335e029cd505aec6a Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Wed, 26 Aug 2026 09:50:48 -0400 Subject: [PATCH 8/9] Updates --- aspnetcore/blazor/security/additional-scenarios.md | 6 +++--- aspnetcore/blazor/security/index.md | 10 +++++----- aspnetcore/blazor/security/webassembly/index.md | 6 +++--- aspnetcore/security/authorization/introduction.md | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/aspnetcore/blazor/security/additional-scenarios.md b/aspnetcore/blazor/security/additional-scenarios.md index f80141a148b9..131fba40ff1a 100644 --- a/aspnetcore/blazor/security/additional-scenarios.md +++ b/aspnetcore/blazor/security/additional-scenarios.md @@ -5,7 +5,7 @@ author: guardrex description: Learn how to configure server-side Blazor and Blazor Web Apps for additional security scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 08/24/2026 +ms.date: 08/26/2026 uid: blazor/security/additional-scenarios --- # ASP.NET Core Blazor additional server-side security scenarios @@ -1371,9 +1371,9 @@ In [Duende IdentityServer](https://duendesoftware.com/products/identityserver), Built-in opaque access token support is under consideration for a future release of .NET. For more information, see [Opaque - reference token validation (`dotnet/aspnetcore` #46026)](https://github.com/dotnet/aspnetcore/issues/46026). -## Patterns to require authorization in a server-side Blazor app +## Server-side Blazor app authorization patterns -*For patterns that apply to Blazor WebAssembly apps, see .* +*For patterns that apply to Blazor WebAssembly apps, see .* Server-side Blazor apps (Blazor Web Apps, Blazor Server apps) usually adopt **either** of the following approaches to require authorization: diff --git a/aspnetcore/blazor/security/index.md b/aspnetcore/blazor/security/index.md index f59e292d2d46..740f23d80482 100644 --- a/aspnetcore/blazor/security/index.md +++ b/aspnetcore/blazor/security/index.md @@ -5,7 +5,7 @@ author: guardrex description: Learn about Blazor authentication and authorization scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett -ms.date: 08/24/2026 +ms.date: 08/26/2026 uid: blazor/security/index --- # ASP.NET Core Blazor authentication and authorization @@ -1811,7 +1811,7 @@ PII refers any information relating to an identified or identifiable natural per :::moniker range=">= aspnetcore-6.0" * Server-side and Blazor Web App resources - * [Patterns to require authorization](xref:blazor/security/additional-scenarios#patterns-to-require-authorization-in-a-server-side-blazor-app) + * [Authorization patterns](xref:blazor/security/additional-scenarios#server-side-blazor-app-authorization-patterns) * [Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app](/entra/identity-platform/quickstart-v2-aspnet-core-webapp) * [Quickstart: Protect an ASP.NET Core web API with Microsoft identity platform](/entra/identity-platform/quickstart-v2-aspnet-core-web-api) * : Includes guidance on: @@ -1830,14 +1830,14 @@ PII refers any information relating to an identified or identifiable natural per * [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links * * [Opaque (reference) access token support](xref:blazor/security/additional-scenarios#opaque-reference-access-token-support) -* [Patterns to require authorization in a Blazor WebAssembly app](xref:blazor/security/webassembly/index#patterns-to-require-authorization-in-a-blazor-webassembly-app) +* [Blazor WebAssembly authorization patterns](xref:blazor/security/webassembly/index#blazor-webassembly-authorization-patterns) :::moniker-end :::moniker range="< aspnetcore-6.0" * Server-side Blazor resources - * [Patterns to require authorization](xref:blazor/security/additional-scenarios#patterns-to-require-authorization-in-a-server-side-blazor-app) + * [Authorization patterns](xref:blazor/security/additional-scenarios#server-side-blazor-app-authorization-patterns) * [Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app](/entra/identity-platform/quickstart-v2-aspnet-core-webapp) * [Quickstart: Protect an ASP.NET Core web API with Microsoft identity platform](/entra/identity-platform/quickstart-v2-aspnet-core-web-api) * : Includes guidance on: @@ -1855,6 +1855,6 @@ PII refers any information relating to an identified or identifiable natural per * [Build a custom version of the Authentication.MSAL JavaScript library](xref:blazor/security/webassembly/additional-scenarios#build-a-custom-version-of-the-authenticationmsal-javascript-library) * [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links * [Opaque (reference) access token support](xref:blazor/security/additional-scenarios#opaque-reference-access-token-support) -* [Patterns to require authorization in a Blazor WebAssembly app](xref:blazor/security/webassembly/index#patterns-to-require-authorization-in-a-blazor-webassembly-app) +* [Blazor WebAssembly authorization patterns](xref:blazor/security/webassembly/index#blazor-webassembly-authorization-patterns) :::moniker-end diff --git a/aspnetcore/blazor/security/webassembly/index.md b/aspnetcore/blazor/security/webassembly/index.md index 89e822c94320..f4e166fd891d 100644 --- a/aspnetcore/blazor/security/webassembly/index.md +++ b/aspnetcore/blazor/security/webassembly/index.md @@ -6,7 +6,7 @@ description: Learn how to secure Blazor WebAssembly apps as single-page applicat monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.custom: sfi-ropc-nochange -ms.date: 08/24/2026 +ms.date: 08/26/2026 uid: blazor/security/webassembly/index --- # Secure ASP.NET Core Blazor WebAssembly @@ -171,9 +171,9 @@ The following authentication scenarios are covered in the .* +*For patterns that apply to server-side Blazor apps (Blazor Web Apps, Blazor Server apps), see .* Unlike server-side Blazor apps, setting an to a policy with is **not** supported. Therefore, the only supported pattern for Blazor WebAssembly apps is to apply the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) ([API documentation](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute)) to Razor components using ***one*** of the following approaches: diff --git a/aspnetcore/security/authorization/introduction.md b/aspnetcore/security/authorization/introduction.md index 03f77d4a75d6..53c4fc892833 100644 --- a/aspnetcore/security/authorization/introduction.md +++ b/aspnetcore/security/authorization/introduction.md @@ -4,7 +4,7 @@ ai-usage: ai-assisted author: wadepickett description: Learn the basics of authorization and how authorization works in ASP.NET Core apps. ms.author: wpickett -ms.date: 08/24/2026 +ms.date: 08/26/2026 uid: security/authorization/introduction --- # Introduction to authorization in ASP.NET Core @@ -30,6 +30,6 @@ For more information, see . * * * -* Patterns to require authorization in Blazor apps - * [Server-side Blazor apps (Blazor Web Apps, Blazor Server apps)](xref:blazor/security/additional-scenarios#patterns-to-require-authorization-in-a-server-side-blazor-app) - * [Blazor WebAssembly apps](xref:blazor/security/webassembly/index#patterns-to-require-authorization-in-a-blazor-webassembly-app) +* Blazor app authorization patterns + * [Server-side Blazor (Blazor Web Apps, Blazor Server apps)](xref:blazor/security/additional-scenarios#server-side-blazor-app-authorization-patterns) + * [Blazor WebAssembly](xref:blazor/security/webassembly/index#blazor-webassembly-authorization-patterns) From f1b2b5c8d65d692d15f072a9c1660f91982fbc55 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 26 Aug 2026 15:43:02 -0400 Subject: [PATCH 9/9] Update aspnetcore/blazor/security/webassembly/index.md Co-authored-by: Wade Pickett --- aspnetcore/blazor/security/webassembly/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/blazor/security/webassembly/index.md b/aspnetcore/blazor/security/webassembly/index.md index f4e166fd891d..b91dc611628f 100644 --- a/aspnetcore/blazor/security/webassembly/index.md +++ b/aspnetcore/blazor/security/webassembly/index.md @@ -175,7 +175,7 @@ The following authentication scenarios are covered in the .* -Unlike server-side Blazor apps, setting an to a policy with is **not** supported. Therefore, the only supported pattern for Blazor WebAssembly apps is to apply the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) ([API documentation](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute)) to Razor components using ***one*** of the following approaches: +Unlike server-side Blazor apps, Blazor WebAssembly apps don't support setting an to a policy with . Therefore, the only supported pattern for Blazor WebAssembly apps is to apply the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute) ([API documentation](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute)) to Razor components using ***one*** of the following approaches: * In the app's imports file, add an [`@using`](xref:mvc/views/razor#using) directive for the namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute).