Skip to content

Commit 9399280

Browse files
authored
Merge pull request #37560 from dotnet/main
Merge to Live
2 parents 1dda901 + c680a4e commit 9399280

48 files changed

Lines changed: 353 additions & 106 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.openpublishing.redirection.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,36 @@
17191719
"redirect_url": "/aspnet/core/fundamentals/validation",
17201720
"redirect_document_id": false
17211721
},
1722+
{
1723+
"source_path": "aspnetcore/log-mon/metrics/metrics.md",
1724+
"redirect_url": "/aspnet/core/metrics/overview",
1725+
"redirect_document_id": false
1726+
},
1727+
{
1728+
"source_path": "aspnetcore/log-mon/metrics/built-in.md",
1729+
"redirect_url": "/aspnet/core/metrics/built-in",
1730+
"redirect_document_id": false
1731+
},
1732+
{
1733+
"source_path": "aspnetcore/log-mon/metrics/built-in-components.md",
1734+
"redirect_url": "/aspnet/core/metrics/blazor",
1735+
"redirect_document_id": false
1736+
},
1737+
{
1738+
"source_path": "aspnetcore/log-mon/metrics/built-in-diagnostics.md",
1739+
"redirect_url": "/aspnet/core/metrics/diagnostics",
1740+
"redirect_document_id": false
1741+
},
1742+
{
1743+
"source_path": "aspnetcore/log-mon/metrics/built-in-http.md",
1744+
"redirect_url": "/aspnet/core/metrics/http",
1745+
"redirect_document_id": false
1746+
},
1747+
{
1748+
"source_path": "aspnetcore/log-mon/metrics/built-in-security.md",
1749+
"redirect_url": "/aspnet/core/metrics/security",
1750+
"redirect_document_id": false
1751+
},
17221752
{
17231753
"source_path": "aspnetcore/blazor/hybrid/tutorials/maui.md",
17241754
"redirect_url": "/dotnet/maui/get-started/first-app",

aspnetcore/blazor/fundamentals/static-files.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
---
22
title: ASP.NET Core Blazor static files
3+
ai-usage: ai-assisted
34
author: guardrex
45
description: Learn how to configure and manage static files for Blazor apps.
56
monikerRange: '>= aspnetcore-3.1'
67
ms.author: wpickett
7-
ms.date: 11/11/2025
8+
ms.date: 08/24/2026
89
uid: blazor/fundamentals/static-files
910
---
1011
# ASP.NET Core Blazor static files
@@ -505,7 +506,7 @@ To create additional file mappings with a <xref:Microsoft.AspNetCore.StaticFiles
505506
app.UseStaticFiles();
506507
```
507508

508-
* You can avoid interfering with serving `_framework/blazor.server.js` by using <xref:Microsoft.AspNetCore.Builder.MapWhenExtensions.MapWhen%2A> to execute a custom static file middleware:
509+
* You can avoid interfering with serving `_framework/blazor.server.js` by using <xref:Microsoft.AspNetCore.Builder.MapWhenExtensions.MapWhen%2A> to execute a custom static files middleware:
509510

510511
```csharp
511512
app.MapWhen(ctx => !ctx.Request.Path
@@ -538,7 +539,7 @@ Add the following `using` statement to the top of the server project's `Program`
538539
using Microsoft.Extensions.FileProviders;
539540
```
540541

541-
In the server project's `Program` file ***before*** the call to <xref:Microsoft.AspNetCore.Builder.StaticFileExtensions.UseStaticFiles%2A>, add the following code:
542+
In the server project's `Program` file ***before*** any calls to <xref:Microsoft.AspNetCore.Builder.StaticAssetsEndpointRouteBuilderExtensions.MapStaticAssets%2A> and <xref:Microsoft.AspNetCore.Builder.StaticFileExtensions.UseStaticFiles%2A>, add the following code:
542543

543544
```csharp
544545
var secondaryProvider = new PhysicalFileProvider(

aspnetcore/blazor/performance/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ builder.Services.ConfigureOpenTelemetryTracerProvider(tracerProvider =>
5151

5252
### Performance meters
5353

54-
For more information on the following performance meters, see <xref:log-mon/metrics/built-in>.
54+
For more information on the following performance meters, see <xref:metrics/built-in>.
5555

5656
`Microsoft.AspNetCore.Components` meter:
5757

@@ -74,7 +74,7 @@ In server-side Blazor apps, additional circuit-specific metrics include:
7474

7575
### Blazor tracing
7676

77-
For more information on the following tracing activities, see <xref:log-mon/metrics/built-in>.
77+
For more information on the following tracing activities, see <xref:metrics/built-in>.
7878

7979
The new activity tracing capabilities use the `Microsoft.AspNetCore.Components` activity source and provide three main types of tracing activities: circuit lifecycle, navigation, and event handling.
8080

aspnetcore/blazor/security/additional-scenarios.md

Lines changed: 209 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
---
2-
title: ASP.NET Core server-side and Blazor Web App additional security scenarios
2+
title: ASP.NET Core Blazor additional server-side security scenarios
3+
ai-usage: ai-assisted
34
author: guardrex
45
description: Learn how to configure server-side Blazor and Blazor Web Apps for additional security scenarios.
56
monikerRange: '>= aspnetcore-3.1'
67
ms.author: wpickett
7-
ms.date: 11/11/2025
8+
ms.date: 08/26/2026
89
uid: blazor/security/additional-scenarios
910
---
10-
# ASP.NET Core server-side and Blazor Web App additional security scenarios
11+
# ASP.NET Core Blazor additional server-side security scenarios
1112

1213
[!INCLUDE[](~/includes/not-latest-version.md)]
1314

@@ -1369,3 +1370,208 @@ The preceding example's placeholders:
13691370
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/).
13701371
13711372
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).
1373+
1374+
## Server-side Blazor app authorization patterns
1375+
1376+
*For patterns that apply to Blazor WebAssembly apps, see <xref:blazor/security/webassembly/index#blazor-webassembly-authorization-patterns>.*
1377+
1378+
Server-side Blazor apps (Blazor Web Apps, Blazor Server apps) usually adopt **either** of the following approaches to require authorization:
1379+
1380+
* 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.
1381+
* 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.
1382+
1383+
### Global authorization via a fallback authorization policy
1384+
1385+
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)).
1386+
1387+
Set the <xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.FallbackPolicy?displayProperty=nameWithType> to a policy with <xref:Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder.RequireAuthenticatedUser%2A>, which only applies when there are no authorization attributes or explicit policies set for a given resource:
1388+
1389+
:::moniker range=">= aspnetcore-6.0"
1390+
1391+
```csharp
1392+
builder.Services.AddAuthorization(options =>
1393+
{
1394+
options.FallbackPolicy = options.DefaultPolicy;
1395+
});
1396+
```
1397+
1398+
:::moniker-end
1399+
1400+
:::moniker range="< aspnetcore-6.0"
1401+
1402+
```csharp
1403+
services.AddAuthorization(options =>
1404+
{
1405+
options.FallbackPolicy = options.DefaultPolicy;
1406+
});
1407+
```
1408+
1409+
:::moniker-end
1410+
1411+
The framework's <xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.DefaultPolicy%2A?displayProperty=nameWithType> 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:
1412+
1413+
:::moniker range=">= aspnetcore-6.0"
1414+
1415+
```csharp
1416+
builder.Services.AddAuthorization(options =>
1417+
{
1418+
options.FallbackPolicy = new AuthorizationPolicyBuilder()
1419+
.RequireAuthenticatedUser()
1420+
.Build();
1421+
});
1422+
```
1423+
1424+
:::moniker-end
1425+
1426+
:::moniker range="< aspnetcore-6.0"
1427+
1428+
```csharp
1429+
services.AddAuthorization(options =>
1430+
{
1431+
options.FallbackPolicy = new AuthorizationPolicyBuilder()
1432+
.RequireAuthenticatedUser()
1433+
.Build();
1434+
});
1435+
```
1436+
1437+
:::moniker-end
1438+
1439+
The app requires an authenticated user for any resource where no specific policy is set.
1440+
1441+
:::moniker range=">= aspnetcore-9.0"
1442+
1443+
If the app's security specification doesn't call for protecting static assets, call <xref:Microsoft.AspNetCore.Builder.AuthorizationEndpointConventionBuilderExtensions.AllowAnonymous%2A?displayProperty=nameWithType> on <xref:Microsoft.AspNetCore.Builder.StaticAssetsEndpointRouteBuilderExtensions.MapStaticAssets%2A>:
1444+
1445+
```csharp
1446+
app.MapStaticAssets().AllowAnonymous();
1447+
```
1448+
1449+
To alternatively allow anonymous access for specific paths, apply the <xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute> to the route pattern inside the endpoint convention lambda of <xref:Microsoft.AspNetCore.StaticAssets.StaticAssetsEndpointConventionBuilder.Add%2A?displayProperty=nameWithType>.
1450+
1451+
> [!IMPORTANT]
1452+
> 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.
1453+
1454+
Place static assets for anonymous access into a single folder. In the following example, endpoint routes with the `/public/` path segment are served anonymously:
1455+
1456+
```csharp
1457+
app.MapStaticAssets()
1458+
.Add(endpointBuilder =>
1459+
{
1460+
if (endpointBuilder is RouteEndpointBuilder routeBuilder &&
1461+
routeBuilder.RoutePattern.RawText?.Contains(
1462+
"/public/", StringComparison.OrdinalIgnoreCase) == true)
1463+
{
1464+
routeBuilder.Metadata.Add(new AllowAnonymousAttribute());
1465+
}
1466+
});
1467+
```
1468+
1469+
The next example demonstrates anonymously serving the uncompressed Blazor script (`_framework/blazor.web.{FINGERPRINT}.js`, where the `{FINGERPRINT}` placeholder is the file's fingerprint):
1470+
1471+
```csharp
1472+
// using System.Text.RegularExpressions;
1473+
1474+
var regex = new Regex(
1475+
@"^_framework/blazor\.web\.[a-z0-9]{10}\.js$", RegexOptions.Compiled);
1476+
1477+
app.MapStaticAssets()
1478+
.Add(endpointBuilder =>
1479+
{
1480+
if (endpointBuilder is RouteEndpointBuilder routeBuilder &&
1481+
regex.IsMatch(routeBuilder.RoutePattern.RawText ?? string.Empty))
1482+
{
1483+
routeBuilder.Metadata.Add(new AllowAnonymousAttribute());
1484+
}
1485+
});
1486+
```
1487+
1488+
:::moniker-end
1489+
1490+
:::moniker range="< aspnetcore-9.0"
1491+
1492+
If the app's security specification doesn't call for protecting static assets, place the call to <xref:Microsoft.AspNetCore.Builder.StaticFileExtensions.UseStaticFiles%2A> ***before*** <xref:Microsoft.AspNetCore.Builder.AuthAppBuilderExtensions.UseAuthentication%2A> and <xref:Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization%2A>:
1493+
1494+
```csharp
1495+
app.UseStaticFiles();
1496+
1497+
app.UseAuthentication();
1498+
app.UseAuthorization();
1499+
```
1500+
1501+
To alternatively allow anonymous access for specific paths, register a separate static files middleware before <xref:Microsoft.AspNetCore.Builder.AuthAppBuilderExtensions.UseAuthentication%2A> and <xref:Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions.UseAuthorization%2A> are called. A second call to <xref:Microsoft.AspNetCore.Builder.StaticFileExtensions.UseStaticFiles%2A> after authorization pipeline processing only serves other static assets if the user is authorized.
1502+
1503+
> [!IMPORTANT]
1504+
> 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.
1505+
1506+
In the following example, static assets in the app's `wwwroot/public` folder are served anonymously:
1507+
1508+
```csharp
1509+
app.UseStaticFiles(new StaticFileOptions {
1510+
FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(
1511+
System.IO.Path.Combine(builder.Environment.WebRootPath, "public")),
1512+
RequestPath = "/public"
1513+
});
1514+
1515+
app.UseAuthentication();
1516+
app.UseAuthorization();
1517+
1518+
app.UseStaticFiles();
1519+
```
1520+
1521+
:::moniker-end
1522+
1523+
Use an [`@using`](xref:mvc/views/razor#using) directive for the <xref:Microsoft.AspNetCore.Authorization?displayProperty=fullName> 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.
1524+
1525+
At the top of `Components/Pages/Home.razor`:
1526+
1527+
```razor
1528+
@page "/"
1529+
@using Microsoft.AspNetCore.Authorization
1530+
@attribute [AllowAnonymous]
1531+
```
1532+
1533+
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.
1534+
1535+
In `Components/Account/Pages/_Imports.razor`:
1536+
1537+
```razor
1538+
@using Microsoft.AspNetCore.Authorization
1539+
@attribute [AllowAnonymous]
1540+
```
1541+
1542+
:::moniker range=">= aspnetcore-5.0"
1543+
1544+
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 <xref:Microsoft.AspNetCore.Builder.AuthorizationEndpointConventionBuilderExtensions.AllowAnonymous%2A?displayProperty=nameWithType>. The following example maps additional Identity endpoints by calling `MapAdditionalIdentityEndpoints`, which returns an <xref:Microsoft.AspNetCore.Builder.IEndpointConventionBuilder>:
1545+
1546+
```csharp
1547+
app.MapAdditionalIdentityEndpoints().AllowAnonymous();
1548+
```
1549+
1550+
> [!NOTE]
1551+
> 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).
1552+
1553+
:::moniker-end
1554+
1555+
### Local authorization via `[Authorize]` attributes
1556+
1557+
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:
1558+
1559+
* In the app's imports file, add an [`@using`](xref:mvc/views/razor#using) directive for the <xref:Microsoft.AspNetCore.Authorization?displayProperty=fullName> namespace with an [`@attribute`](xref:mvc/views/razor#attribute) directive for the [`[Authorize]` attribute](xref:blazor/security/index#authorize-attribute).
1560+
1561+
`_Imports.razor`:
1562+
1563+
```razor
1564+
@using Microsoft.AspNetCore.Authorization
1565+
@attribute [Authorize]
1566+
```
1567+
1568+
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.
1569+
1570+
* 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 <xref:Microsoft.AspNetCore.Authorization?displayProperty=fullName> namespace:
1571+
1572+
```razor
1573+
@using Microsoft.AspNetCore.Authorization
1574+
@attribute [Authorize]
1575+
```
1576+
1577+
The [`@using`](xref:mvc/views/razor#using) directive for the <xref:Microsoft.AspNetCore.Authorization?displayProperty=fullName> 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.

aspnetcore/blazor/security/index.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ author: guardrex
55
description: Learn about Blazor authentication and authorization scenarios.
66
monikerRange: '>= aspnetcore-3.1'
77
ms.author: wpickett
8-
ms.date: 11/11/2025
8+
ms.date: 08/26/2026
99
uid: blazor/security/index
1010
---
1111
# ASP.NET Core Blazor authentication and authorization
@@ -1811,6 +1811,7 @@ PII refers any information relating to an identified or identifiable natural per
18111811
:::moniker range=">= aspnetcore-6.0"
18121812

18131813
* Server-side and Blazor Web App resources
1814+
* [Authorization patterns](xref:blazor/security/additional-scenarios#server-side-blazor-app-authorization-patterns)
18141815
* [Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app](/entra/identity-platform/quickstart-v2-aspnet-core-webapp)
18151816
* [Quickstart: Protect an ASP.NET Core web API with Microsoft identity platform](/entra/identity-platform/quickstart-v2-aspnet-core-web-api)
18161817
* <xref:host-and-deploy/proxy-load-balancer>: Includes guidance on:
@@ -1829,12 +1830,14 @@ PII refers any information relating to an identified or identifiable natural per
18291830
* [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links
18301831
* <xref:blazor/hybrid/security/index>
18311832
* [Opaque (reference) access token support](xref:blazor/security/additional-scenarios#opaque-reference-access-token-support)
1833+
* [Blazor WebAssembly authorization patterns](xref:blazor/security/webassembly/index#blazor-webassembly-authorization-patterns)
18321834

18331835
:::moniker-end
18341836

18351837
:::moniker range="< aspnetcore-6.0"
18361838

18371839
* Server-side Blazor resources
1840+
* [Authorization patterns](xref:blazor/security/additional-scenarios#server-side-blazor-app-authorization-patterns)
18381841
* [Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app](/entra/identity-platform/quickstart-v2-aspnet-core-webapp)
18391842
* [Quickstart: Protect an ASP.NET Core web API with Microsoft identity platform](/entra/identity-platform/quickstart-v2-aspnet-core-web-api)
18401843
* <xref:host-and-deploy/proxy-load-balancer>: Includes guidance on:
@@ -1852,5 +1855,6 @@ PII refers any information relating to an identified or identifiable natural per
18521855
* [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)
18531856
* [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links
18541857
* [Opaque (reference) access token support](xref:blazor/security/additional-scenarios#opaque-reference-access-token-support)
1858+
* [Blazor WebAssembly authorization patterns](xref:blazor/security/webassembly/index#blazor-webassembly-authorization-patterns)
18551859

18561860
:::moniker-end

0 commit comments

Comments
 (0)