diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index 4f4e92e694b1..51f85a82eab2 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -1,10 +1,11 @@ --- 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' ms.author: wpickett -ms.date: 11/11/2025 +ms.date: 08/24/2026 uid: blazor/fundamentals/static-files --- # ASP.NET Core Blazor static files @@ -505,7 +506,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 +539,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 33faced721c4..131fba40ff1a 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: 11/11/2025 +ms.date: 08/26/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)] @@ -1369,3 +1370,208 @@ 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). + +## Server-side Blazor app authorization patterns + +*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: + +* 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 + +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 , 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 => +{ + options.FallbackPolicy = options.DefaultPolicy; +}); +``` + +:::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 => +{ + options.FallbackPolicy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build(); +}); +``` + +:::moniker-end + +:::moniker range="< aspnetcore-6.0" + +```csharp +services.AddAuthorization(options => +{ + options.FallbackPolicy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build(); +}); +``` + +:::moniker-end + +The app requires an authenticated user for any resource where no specific policy is set. + +:::moniker range=">= aspnetcore-9.0" + +If the app's security specification doesn't call for protecting static assets, call on : + +```csharp +app.MapStaticAssets().AllowAnonymous(); +``` + +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 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: + +```csharp +app.MapStaticAssets() + .Add(endpointBuilder => + { + if (endpointBuilder is RouteEndpointBuilder routeBuilder && + routeBuilder.RoutePattern.RawText?.Contains( + "/public/", StringComparison.OrdinalIgnoreCase) == true) + { + routeBuilder.Metadata.Add(new AllowAnonymousAttribute()); + } + }); +``` + +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()); + } + }); +``` + +:::moniker-end + +:::moniker range="< aspnetcore-9.0" + +If the app's security specification doesn't call for protecting static assets, place the call to ***before*** and : + +```csharp +app.UseStaticFiles(); + +app.UseAuthentication(); +app.UseAuthorization(); +``` + +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 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: + +```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 + +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. + +At the top of `Components/Pages/Home.razor`: + +```razor +@page "/" +@using Microsoft.AspNetCore.Authorization +@attribute [AllowAnonymous] +``` + +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`: + +```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 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(); +``` + +> [!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 ***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). + + `_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) 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 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 994936c084e6..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: 11/11/2025 +ms.date: 08/26/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 + * [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: @@ -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) +* [Blazor WebAssembly authorization patterns](xref:blazor/security/webassembly/index#blazor-webassembly-authorization-patterns) :::moniker-end :::moniker range="< aspnetcore-6.0" * Server-side Blazor resources + * [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: @@ -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) +* [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 55ec2a3054da..b91dc611628f 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: 11/11/2025 +ms.date: 08/26/2026 uid: blazor/security/webassembly/index --- # Secure ASP.NET Core Blazor WebAssembly @@ -170,9 +171,11 @@ The following authentication scenarios are covered in the .* + +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). @@ -199,9 +202,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/security/authorization/introduction.md b/aspnetcore/security/authorization/introduction.md index 2e5d4ad4daef..53c4fc892833 100644 --- a/aspnetcore/security/authorization/introduction.md +++ b/aspnetcore/security/authorization/introduction.md @@ -1,12 +1,11 @@ --- 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 -ms.date: 05/15/2026 +ms.date: 08/26/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 +21,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), are defined in the namespace. -Consult the documentation on [simple authorization](xref:security/authorization/simple). +For more information, see . -## Related content +## Additional resources * * * +* 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)