Skip to content

Commit 061744d

Browse files
authored
Merge pull request #35042 from dotnet/main
2 parents 8168f48 + 0c45458 commit 061744d

File tree

6 files changed

+223
-3
lines changed

6 files changed

+223
-3
lines changed

aspnetcore/blazor/call-web-api.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,54 @@ requestMessage.Headers.Add("X-Requested-With", [ "XMLHttpRequest" ]);
972972

973973
Blazor's client-side implementation of <xref:System.Net.Http.HttpClient> uses [Fetch API](https://developer.mozilla.org/docs/Web/API/fetch) and configures the underlying [request-specific Fetch API options](https://developer.mozilla.org/docs/Web/API/fetch#Parameters) via <xref:System.Net.Http.HttpRequestMessage> extension methods and <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions>. Set additional options using the generic <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserRequestOption%2A> extension method. Blazor and the underlying Fetch API don't directly add or modify request headers. For more information on how user agents, such as browsers, interact with headers, consult external user agent documentation sets and other web resources.
974974

975-
The HTTP response is typically buffered to enable support for synchronous reads on the response content. To enable support for response streaming, use the <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserResponseStreamingEnabled%2A> extension method on the request.
975+
:::moniker range=">= aspnetcore-10.0"
976+
977+
Response streaming is enabled by default.
978+
979+
Calling <xref:System.Net.Http.HttpContent.ReadAsStreamAsync%2A?displayProperty=nameWithType> for an <xref:System.Net.Http.HttpResponseMessage.Content%2A?displayProperty=nameWithType> (`response.Content.ReadAsStreamAsync()`) returns a [`BrowserHttpReadStream` (reference source)](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs), not a <xref:System.IO.MemoryStream>. `BrowserHttpReadStream` doesn't support synchronous operations, such as `Stream.Read(Span<Byte>)`. If your code uses synchronous operations, you can opt-out of response streaming or copy the <xref:System.IO.Stream> into a <xref:System.IO.MemoryStream> yourself.
980+
981+
[!INCLUDE[](~/includes/aspnetcore-repo-ref-source-links.md)]
982+
983+
<!-- UPDATE 10.0 - Tracking on https://github.com/dotnet/runtime/issues/97449
984+
985+
To opt-out of response streaming globally, use either of the following approaches:
986+
987+
* Add the `<WasmEnableStreamingResponse>` property to the project file with a value of `false`:
988+
989+
```xml
990+
<WasmEnableStreamingResponse>false</WasmEnableStreamingResponse>
991+
```
992+
993+
* Set the `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` environment variable to `false` or `0`.
994+
995+
-->
996+
997+
To opt-out of response streaming globally, set the `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` environment variable to `false` or `0`.
998+
999+
To opt-out of response streaming for an individual request, set <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserResponseStreamingEnabled%2A> to `false` on the <xref:System.Net.Http.HttpRequestMessage> (`requestMessage` in the following example):
1000+
1001+
```csharp
1002+
requestMessage.SetBrowserResponseStreamingEnabled(false);
1003+
```
1004+
1005+
:::moniker-end
1006+
1007+
:::moniker range="< aspnetcore-10.0"
1008+
1009+
The HTTP response is typically buffered to enable support for synchronous reads on the response content. To enable support for response streaming, set <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserResponseStreamingEnabled%2A> to `true` on the <xref:System.Net.Http.HttpRequestMessage>:
1010+
1011+
```csharp
1012+
requestMessage.SetBrowserResponseStreamingEnabled(true);
1013+
```
1014+
1015+
By default, [`HttpCompletionOption.ResponseContentRead`](xref:System.Net.Http.HttpCompletionOption) is set, which results in the <xref:System.Net.Http.HttpClient> completing after reading the entire response, including the content. In order to be able to use the <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserResponseStreamingEnabled%2A> option on large files, set [`HttpCompletionOption.ResponseHeadersRead`](xref:System.Net.Http.HttpCompletionOption) to avoid caching the file's content in memory:
1016+
1017+
```diff
1018+
- var response = await Http.SendAsync(requestMessage);
1019+
+ var response = await Http.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);
1020+
```
1021+
1022+
:::moniker-end
9761023

9771024
To include credentials in a cross-origin request, use the <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserRequestCredentials%2A> extension method:
9781025

aspnetcore/blazor/security/blazor-web-app-with-entra.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID
33
author: guardrex
4-
description: Learn how to secure a Blazor WebAssembly App with Microsoft Entra ID.
4+
description: Learn how to secure a Blazor Web App with Microsoft Entra ID.
55
monikerRange: '>= aspnetcore-9.0'
66
ms.author: riande
77
ms.custom: mvc

aspnetcore/blazor/security/blazor-web-app-with-oidc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Secure an ASP.NET Core Blazor Web App with OpenID Connect (OIDC)
33
author: guardrex
4-
description: Learn how to secure a Blazor WebAssembly App with OpenID Connect (OIDC).
4+
description: Learn how to secure a Blazor Web App with OpenID Connect (OIDC).
55
monikerRange: '>= aspnetcore-8.0'
66
ms.author: riande
77
ms.custom: mvc
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
title: Secure an ASP.NET Core Blazor Web App with Windows Authentication
3+
author: guardrex
4+
description: Learn how to secure a Blazor Web App with Windows Authentication.
5+
monikerRange: '>= aspnetcore-9.0'
6+
ms.author: riande
7+
ms.custom: mvc
8+
ms.date: 03/25/2025
9+
uid: blazor/security/blazor-web-app-windows-authentication
10+
---
11+
# Secure an ASP.NET Core Blazor Web App with Windows Authentication
12+
13+
<!-- UPDATE 10.0 - Enable after release
14+
15+
[!INCLUDE[](~/includes/not-latest-version-without-not-supported-content.md)]
16+
17+
-->
18+
19+
This article describes how to secure a Blazor Web App with [Windows Authentication](/windows-server/security/windows-authentication/windows-authentication-overview) using a sample app. For more information, see <xref:security/authentication/windowsauth>.
20+
21+
The app specification for the Blazor Web App:
22+
23+
* Adopts the [Interactive Server render mode with global interactivity](xref:blazor/components/render-modes).
24+
* Establishes an [authorization policy](xref:security/authorization/policies) for a [Windows security identifier](/windows-server/identity/ad-ds/manage/understand-security-identifiers) to access a secure page.
25+
26+
## Sample app
27+
28+
Access the sample through the latest version folder in the Blazor samples repository with the following link. The sample is in the `BlazorWebAppWinAuthServer` folder for .NET 9 or later.
29+
30+
[View or download sample code](https://github.com/dotnet/blazor-samples) ([how to download](xref:blazor/fundamentals/index#sample-apps))
31+
32+
## Configuration
33+
34+
The sample app doesn't require configuration to run locally.
35+
36+
When deployed to a host, such as IIS, the app must adopt impersonation to run under the user's account. For more information, see <xref:security/authentication/windowsauth#impersonation>.
37+
38+
## Sample app code
39+
40+
Inspect the `Program` file in the sample app for the following API calls.
41+
42+
<xref:Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions.AddAuthentication%2A> is called using the <xref:Microsoft.AspNetCore.Authentication.Negotiate.NegotiateDefaults.AuthenticationScheme%2A?displayProperty=nameWithType> authentication scheme. <xref:Microsoft.Extensions.DependencyInjection.NegotiateExtensions.AddNegotiate%2A> configures the <xref:Microsoft.AspNetCore.Authentication.AuthenticationBuilder> to use Negotiate (also known as Windows, Kerberos, or NTLM) authentication, and the authentication handler supports Kerberos on Windows and Linux servers:
43+
44+
```csharp
45+
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
46+
.AddNegotiate();
47+
```
48+
49+
<xref:Microsoft.Extensions.DependencyInjection.PolicyServiceCollectionExtensions.AddAuthorization%2A> adds authorization policy services. <xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.FallbackPolicy%2A?displayProperty=nameWithType> sets the fallback authorization policy, which is set to the default policy (<xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.DefaultPolicy%2A?displayProperty=nameWithType>). The default policy requires an authenticated user to access the app:
50+
51+
```csharp
52+
builder.Services.AddAuthorization(options =>
53+
{
54+
options.FallbackPolicy = options.DefaultPolicy;
55+
});
56+
```
57+
58+
<xref:Microsoft.Extensions.DependencyInjection.CascadingAuthenticationStateServiceCollectionExtensions.AddCascadingAuthenticationState%2A> adds cascading authentication state to the service collection. This is equivalent to placing a `CascadingAuthenticationState` component at the root of the app's component hierarchy:
59+
60+
```csharp
61+
builder.Services.AddCascadingAuthenticationState();
62+
```
63+
64+
An [authorization policy](xref:security/authorization/policies) is added for a [Windows security identifier (SID)](/windows-server/identity/ad-ds/manage/understand-security-identifiers). The `S-1-5-113` well-known SID in the following example indicates that the user is a local account, which restricts network sign-in to local accounts instead of "administrator" or equivalent accounts:
65+
66+
```csharp
67+
builder.Services.AddAuthorizationBuilder()
68+
.AddPolicy("LocalAccount", policy =>
69+
policy.RequireClaim(
70+
"http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid",
71+
"S-1-5-113"));
72+
```
73+
74+
The authorization policy is enforced by the `LocalAccountOnly` component.
75+
76+
`Components/Pages/LocalAccountOnly.razor`:
77+
78+
```razor
79+
@page "/local-account-only"
80+
@using Microsoft.AspNetCore.Authorization
81+
@attribute [Authorize("LocalAccount")]
82+
83+
<h1>Local Account Only</h1>
84+
85+
<p>
86+
You can only reach this page by satisfying the
87+
<code>LocalAccount</code> authorization policy.
88+
</p>
89+
```
90+
91+
The `UserClaims` component lists the user's claims, which includes the user's Windows security identifiers (SIDs).
92+
93+
`Components/Pages/UserClaims.razor`:
94+
95+
```razor
96+
@page "/user-claims"
97+
@using System.Security.Claims
98+
@using Microsoft.AspNetCore.Authorization
99+
@attribute [Authorize]
100+
101+
<PageTitle>User Claims</PageTitle>
102+
103+
<h1>User Claims</h1>
104+
105+
@if (claims.Any())
106+
{
107+
<ul>
108+
@foreach (var claim in claims)
109+
{
110+
<li><b>@claim.Type:</b> @claim.Value</li>
111+
}
112+
</ul>
113+
}
114+
115+
@code {
116+
private IEnumerable<Claim> claims = [];
117+
118+
[CascadingParameter]
119+
private Task<AuthenticationState>? AuthState { get; set; }
120+
121+
protected override async Task OnInitializedAsync()
122+
{
123+
if (AuthState == null)
124+
{
125+
return;
126+
}
127+
128+
var authState = await AuthState;
129+
claims = authState.User.Claims;
130+
}
131+
}
132+
```
133+
134+
## Additional resources
135+
136+
* <xref:security/authentication/windowsauth>
137+
* [Security identifiers (Windows Server documentation)](/windows-server/identity/ad-ds/manage/understand-security-identifiers)

aspnetcore/release-notes/aspnetcore-10/includes/blazor.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,37 @@ The following example uses the `CloseColumnOptionsAsync` method to close the col
8989
movies.Where(m => m.Title!.Contains(titleFilter));
9090
}
9191
```
92+
93+
<!-- PREVIEW 3 ..... NOTE CONTENT CHANGE FOR `<WasmEnableStreamingResponse>` BELOW!!!!!
94+
95+
### Response streaming is opt-in and how to opt-out
96+
97+
In prior Blazor releases, response streaming for <xref:System.Net.Http.HttpClient> requests was opt-in. Now, response streaming is enabled by default.
98+
99+
This is a breaking change because calling <xref:System.Net.Http.HttpContent.ReadAsStreamAsync%2A?displayProperty=nameWithType> for an <xref:System.Net.Http.HttpResponseMessage.Content%2A?displayProperty=nameWithType> (`response.Content.ReadAsStreamAsync()`) returns a `BrowserHttpReadStream` and no longer a <xref:System.IO.MemoryStream>. `BrowserHttpReadStream` doesn't support synchronous operations, such as `Stream.Read(Span<Byte>)`. If your code uses synchronous operations, you can opt-out of response streaming or copy the <xref:System.IO.Stream> into a <xref:System.IO.MemoryStream> yourself.
100+
101+
DON'T USE (comment out) ..............
102+
103+
To opt-out of response streaming globally, use either of the following approaches:
104+
105+
* Add the `<WasmEnableStreamingResponse>` property to the project file with a value of `false`:
106+
107+
```xml
108+
<WasmEnableStreamingResponse>false</WasmEnableStreamingResponse>
109+
```
110+
111+
* Set the `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` environment variable to `false` or `0`.
112+
113+
..................... UNTIL https://github.com/dotnet/runtime/issues/97449 IS RESOLVED AND RELEASED.
114+
115+
To opt-out of response streaming globally, set the `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` environment variable to `false` or `0`.
116+
117+
To opt-out of response streaming for an individual request, set <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserResponseStreamingEnabled%2A> to `false` on the <xref:System.Net.Http.HttpRequestMessage> (`requestMessage` in the following example):
118+
119+
```csharp
120+
requestMessage.SetBrowserResponseStreamingEnabled(false);
121+
```
122+
123+
For more information, see [`HttpClient` and `HttpRequestMessage` with Fetch API request options (*Call web API* article)](xref:blazor/call-web-api?view=aspnetcore-10.0#httpclient-and-httprequestmessage-with-fetch-api-request-options).
124+
125+
-->

aspnetcore/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,8 @@ items:
624624
uid: blazor/security/blazor-web-app-entra
625625
- name: Blazor Web App with OIDC
626626
uid: blazor/security/blazor-web-app-oidc
627+
- name: Blazor Web App with Windows Auth
628+
uid: blazor/security/blazor-web-app-windows-authentication
627629
- name: Static server-side rendering threats
628630
uid: blazor/security/static-server-side-rendering
629631
- name: Interactive server-side rendering threats

0 commit comments

Comments
 (0)