diff --git a/aspnetcore/blazor/debug.md b/aspnetcore/blazor/debug.md index b47fbb5c16a9..478283c731ae 100644 --- a/aspnetcore/blazor/debug.md +++ b/aspnetcore/blazor/debug.md @@ -444,7 +444,7 @@ To break on unhandled exceptions: ## Browser source maps -Browser source maps allow the browser to map compiled files back to their original source files and are commonly used for client-side debugging. However, Blazor doesn't currently map C# directly to JavaScript/WASM. Instead, Blazor does IL interpretation within the browser, so source maps aren't relevant. +Browser source maps allow the browser to map compiled files back to their original source files and are commonly used for client-side debugging. However, Blazor doesn't currently map C# directly to JavaScript/Wasm. Instead, Blazor does IL interpretation within the browser, so source maps aren't relevant. ## Firewall configuration diff --git a/aspnetcore/blazor/fundamentals/handle-errors.md b/aspnetcore/blazor/fundamentals/handle-errors.md index 6d0805d1b03c..2fcd0ce91e52 100644 --- a/aspnetcore/blazor/fundamentals/handle-errors.md +++ b/aspnetcore/blazor/fundamentals/handle-errors.md @@ -719,7 +719,7 @@ Because the approaches in this section handle errors with a [`try-catch`](/dotne If an unhandled exception occurs, the exception is logged to instances configured in the service container. Blazor apps log console output with the Console Logging Provider. Consider logging to a location on the server (or backend web API for client-side apps) with a provider that manages log size and log rotation. Alternatively, the app can use an Application Performance Management (APM) service, such as [Azure Application Insights (Azure Monitor)](/azure/azure-monitor/app/app-insights-overview). > [!NOTE] -> Native [Application Insights](/azure/azure-monitor/app/app-insights-overview) features to support client-side apps and native Blazor framework support for [Google Analytics](https://analytics.google.com/analytics/web/) might become available in future releases of these technologies. For more information, see [Support App Insights in Blazor WASM Client Side (microsoft/ApplicationInsights-dotnet #2143)](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2143) and [Web analytics and diagnostics (includes links to community implementations) (dotnet/aspnetcore #5461)](https://github.com/dotnet/aspnetcore/issues/5461). In the meantime, a client-side app can use the [Application Insights JavaScript SDK](/azure/azure-monitor/app/javascript) with [JS interop](xref:blazor/js-interop/call-javascript-from-dotnet) to log errors directly to Application Insights from a client-side app. +> Native [Application Insights](/azure/azure-monitor/app/app-insights-overview) features to support client-side apps and native Blazor framework support for [Google Analytics](https://analytics.google.com/analytics/web/) might become available in future releases of these technologies. For more information, see [Support App Insights in Blazor WASM Client Side (`microsoft/ApplicationInsights-dotnet` #2143)](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2143) and [Web analytics and diagnostics (includes links to community implementations) (`dotnet/aspnetcore` #5461)](https://github.com/dotnet/aspnetcore/issues/5461). In the meantime, a client-side app can use the [Application Insights JavaScript SDK](/azure/azure-monitor/app/javascript) with [JS interop](xref:blazor/js-interop/call-javascript-from-dotnet) to log errors directly to Application Insights from a client-side app. During development in a Blazor app operating over a circuit, the app usually sends the full details of exceptions to the browser's console to aid in debugging. In production, detailed errors aren't sent to clients, but an exception's full details are logged on the server. @@ -747,7 +747,7 @@ For more information, see the following articles: * ‡ * -†Native [Application Insights](/azure/azure-monitor/app/app-insights-overview) features to support client-side apps and native Blazor framework support for [Google Analytics](https://analytics.google.com/analytics/web/) might become available in future releases of these technologies. For more information, see [Support App Insights in Blazor WASM Client Side (microsoft/ApplicationInsights-dotnet #2143)](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2143) and [Web analytics and diagnostics (includes links to community implementations) (dotnet/aspnetcore #5461)](https://github.com/dotnet/aspnetcore/issues/5461). In the meantime, a client-side app can use the [Application Insights JavaScript SDK](/azure/azure-monitor/app/javascript) with [JS interop](xref:blazor/js-interop/call-javascript-from-dotnet) to log errors directly to Application Insights from a client-side app. +†Native [Application Insights](/azure/azure-monitor/app/app-insights-overview) features to support client-side apps and native Blazor framework support for [Google Analytics](https://analytics.google.com/analytics/web/) might become available in future releases of these technologies. For more information, see [Support App Insights in Blazor WASM Client Side (`microsoft/ApplicationInsights-dotnet` #2143)](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2143) and [Web analytics and diagnostics (includes links to community implementations) (`dotnet/aspnetcore` #5461)](https://github.com/dotnet/aspnetcore/issues/5461). In the meantime, a client-side app can use the [Application Insights JavaScript SDK](/azure/azure-monitor/app/javascript) with [JS interop](xref:blazor/js-interop/call-javascript-from-dotnet) to log errors directly to Application Insights from a client-side app. ‡Applies to server-side ASP.NET Core apps that are web API backend apps for Blazor apps. Client-side apps trap and send error information to a web API, which logs the error information to a persistent logging provider. diff --git a/aspnetcore/blazor/host-and-deploy/webassembly/deployment-layout.md b/aspnetcore/blazor/host-and-deploy/webassembly/deployment-layout.md index f9ce08363b64..992c12093031 100644 --- a/aspnetcore/blazor/host-and-deploy/webassembly/deployment-layout.md +++ b/aspnetcore/blazor/host-and-deploy/webassembly/deployment-layout.md @@ -126,7 +126,7 @@ The following example `BundleBlazorAssets` class is a starting point for further * In the `Execute` method, the bundle is created from the following three file types: * JavaScript files (`dotnet.js`) - * WASM files (`dotnet.wasm`) + * WebAssembly (Wasm) files (`dotnet.wasm`) * App DLLs (`.dll`) * A `multipart/form-data` bundle is created. Each file is added to the bundle with its respective descriptions via the [Content-Disposition header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Disposition) and the [Content-Type header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Type). * After the bundle is created, the bundle is written to a file. @@ -135,7 +135,7 @@ The following example `BundleBlazorAssets` class is a starting point for further * The URL path relative to the root of the Blazor WebAssembly app. * The name of the extension, which groups the files produced by a given extension. -After accomplishing the preceding goals, the MSBuild task is created for customizing the Blazor publish output. Blazor takes care of gathering the extensions and making sure that the extensions are copied to the correct location in the publish output folder (for example, `bin\Release\net6.0\publish`). The same optimizations (for example, compression) are applied to the JavaScript, WASM, and DLL files as Blazor applies to other files. +After accomplishing the preceding goals, the MSBuild task is created for customizing the Blazor publish output. Blazor takes care of gathering the extensions and making sure that the extensions are copied to the correct location in the publish output folder (for example, `bin\Release\net6.0\publish`). The same optimizations (for example, compression) are applied to the JavaScript, Wasm, and DLL files as Blazor applies to other files. `Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/BundleBlazorAssets.cs`: diff --git a/aspnetcore/blazor/hosting-models.md b/aspnetcore/blazor/hosting-models.md index f84eec1bec4b..f5bcf51df220 100644 --- a/aspnetcore/blazor/hosting-models.md +++ b/aspnetcore/blazor/hosting-models.md @@ -32,13 +32,13 @@ This article explains Blazor hosting models and how to choose which one to use. :::moniker range=">= aspnetcore-6.0" -Blazor is a web framework for building web UI components ([Razor components](xref:blazor/components/index)) that can be hosted in different ways. Razor components can run server-side in ASP.NET Core (*Blazor Server*) versus client-side in the browser on a [WebAssembly](https://webassembly.org/)-based .NET runtime (*Blazor WebAssembly*, *Blazor WASM*). You can also host Razor components in native mobile and desktop apps that render to an embedded Web View control (*Blazor Hybrid*). Regardless of the hosting model, the way you build Razor components *is the same*. The same Razor components can be used with any of the hosting models unchanged. +Blazor is a web framework for building web UI components ([Razor components](xref:blazor/components/index)) that can be hosted in different ways. Razor components can run server-side in ASP.NET Core (*Blazor Server*) versus client-side in the browser on a [WebAssembly](https://webassembly.org/)-based .NET runtime (*Blazor WebAssembly*, *Blazor Wasm*). You can also host Razor components in native mobile and desktop apps that render to an embedded Web View control (*Blazor Hybrid*). Regardless of the hosting model, the way you build Razor components *is the same*. The same Razor components can be used with any of the hosting models unchanged. :::moniker-end :::moniker range="< aspnetcore-6.0" -Blazor is a web framework for building web UI components ([Razor components](xref:blazor/components/index)) that can be hosted in different ways. Razor components can run server-side in ASP.NET Core (*Blazor Server*) versus client-side in the browser on a [WebAssembly](https://webassembly.org/)-based .NET runtime (*Blazor WebAssembly*, *Blazor WASM*). Regardless of the hosting model, the way you build Razor components *is the same*. The same Razor components can be used with any of the hosting models unchanged. +Blazor is a web framework for building web UI components ([Razor components](xref:blazor/components/index)) that can be hosted in different ways. Razor components can run server-side in ASP.NET Core (*Blazor Server*) versus client-side in the browser on a [WebAssembly](https://webassembly.org/)-based .NET runtime (*Blazor WebAssembly*, *Blazor Wasm*). Regardless of the hosting model, the way you build Razor components *is the same*. The same Razor components can be used with any of the hosting models unchanged. :::moniker-end @@ -203,7 +203,7 @@ Select the Blazor hosting model based on the app's feature requirements. The fol Blazor Hybrid apps include .NET MAUI, WPF, and Windows Forms framework apps. -Feature | Blazor Server | Blazor WebAssembly (WASM) | Blazor Hybrid +Feature | Blazor Server | Blazor WebAssembly (Wasm) | Blazor Hybrid --- | :---: | :---: | :---: [Complete .NET API compatibility](#complete-net-api-compatibility) | Supported | Not supported | Supported [Direct access to server and network resources](#direct-access-to-server-and-network-resources) | Supported | Not supported† | Not supported† @@ -223,7 +223,7 @@ Feature | Blazor Server | Blazor WebAssembly (WASM) | Blazor Hybrid :::moniker range="< aspnetcore-6.0" -Feature | Blazor Server | Blazor WebAssembly (WASM) +Feature | Blazor Server | Blazor WebAssembly (Wasm) --- | :---: | :---: [Complete .NET API compatibility](#complete-net-api-compatibility) | Supported | Not supported [Direct access to server and network resources](#direct-access-to-server-and-network-resources) | Supported | Not supported† diff --git a/aspnetcore/blazor/performance/webassembly-runtime-performance.md b/aspnetcore/blazor/performance/webassembly-runtime-performance.md index 73841994555a..660acdc9dab2 100644 --- a/aspnetcore/blazor/performance/webassembly-runtime-performance.md +++ b/aspnetcore/blazor/performance/webassembly-runtime-performance.md @@ -20,7 +20,7 @@ This article provides guidance on Blazor WebAssembly runtime performance. ## Potentially reduced performance with Microsoft Edge enhanced security -The Microsoft Edge browser's WebAssembly (WASM) interpreter running in [enhanced security mode](/DeployEdge/microsoft-edge-security-browse-safer) might not yield the same performance as when Blazor is running without enhanced security. If enhanced security mode is enabled and an app's performance is degraded, we recommend adding the site as an [exception](/DeployEdge/microsoft-edge-security-browse-safer#enhanced-security-sites) to opt out of enhanced security mode. +The Microsoft Edge browser's WebAssembly (Wasm) interpreter running in [enhanced security mode](/DeployEdge/microsoft-edge-security-browse-safer) might not yield the same performance as when Blazor is running without enhanced security. If enhanced security mode is enabled and an app's performance is degraded, we recommend adding the site as an [exception](/DeployEdge/microsoft-edge-security-browse-safer#enhanced-security-sites) to opt out of enhanced security mode. :::moniker range=">= aspnetcore-8.0" diff --git a/aspnetcore/blazor/state-management/prerendered-state-persistence.md b/aspnetcore/blazor/state-management/prerendered-state-persistence.md index 5f033fdb1031..ffe4c5eb659b 100644 --- a/aspnetcore/blazor/state-management/prerendered-state-persistence.md +++ b/aspnetcore/blazor/state-management/prerendered-state-persistence.md @@ -32,6 +32,10 @@ The first logged count occurs during prerendering. The count is set again after To retain the initial value of the counter during prerendering, Blazor supports persisting state in a prerendered page using the service (and for components embedded into pages or views of Razor Pages or MVC apps, the [Persist Component State Tag Helper](xref:mvc/views/tag-helpers/builtin-th/persist-component-state-tag-helper)). +By initializing components with the same state used during prerendering, any expensive initialization steps are only executed once. The rendered UI also matches the prerendered UI, so no flicker occurs in the browser. + +The persisted prerendered state is transferred to the client, where it's used to restore the component state. During client-side rendering (CSR, `InteractiveWebAssembly`), the data is exposed to the browser and must not contain sensitive, private information. During interactive server-side rendering (interactive SSR, `InteractiveServer`), [ASP.NET Core Data Protection](xref:security/data-protection/introduction) ensures that the data is transferred securely. The `InteractiveAuto` render mode combines WebAssembly and Server interactivity, so it's necessary to consider data exposure to the browser, as in the CSR case. + :::moniker range=">= aspnetcore-10.0" @@ -136,6 +140,8 @@ In the following example that serializes state for multiple components of the sa } ``` +## Serialize state for services + In the following example that serializes state for a dependency injection service: * Properties annotated with the `[PersistentState]` attribute are serialized during prerendering and deserialized when the app becomes interactive. @@ -148,12 +154,19 @@ In the following example that serializes state for a dependency injection servic > [!NOTE] > Only persisting scoped services is supported. - +Serialized properties are identified from the actual service instance: -`CounterService.cs`: +* This approach allows marking an abstraction as a persistent service. +* Enables actual implementations to be internal or different types. +* Supports shared code in different assemblies. +* Results in each instance exposing the same properties. + +The following counter service, `CounterTracker`, marks its current count property, `CurrentCount` with the `[PersistentState]` attribute. The property is serialized during prerendering and deserialized when the app becomes interactive wherever the service is injected. + +`CounterTracker.cs`: ```csharp -public class CounterService +public class CounterTracker { [PersistentState] public int CurrentCount { get; set; } @@ -165,19 +178,60 @@ public class CounterService } ``` -In `Program.cs`: +In the `Program` file, register the scoped service and register the service for persistence with `RegisterPersistentService`. In the following example, the `CounterTracker` service is available for both the Interactive Server and Interactive WebAssembly render modes if a component renders in either of those modes because it's registered with `RenderMode.InteractiveAuto`. + +If the `Program` file doesn't already use the namespace, add the following `using` statement to the top of the file: ```csharp +using Microsoft.AspNetCore.Components.Web; +``` + +Where services are registered in the `Program` file: + +```csharp +builder.Services.AddScoped(); + builder.Services.AddRazorComponents() - .RegisterPersistentService(RenderMode.InteractiveAuto); + .RegisterPersistentService(RenderMode.InteractiveAuto); ``` -Serialized properties are identified from the actual service instance: +Inject the `CounterTracker` service into a component and use it to increment a counter. For demonstration purposes in the following example, the value of the service's `CurrentCount` property is set to 10 only during prerendering. -* This approach allows marking an abstraction as a persistent service. -* Enables actual implementations to be internal or different types. -* Supports shared code in different assemblies. -* Results in each instance exposing the same properties. +`Pages/Counter.razor`: + +```razor +@page "/counter" +@inject CounterTracker CounterTracker + +Counter + +

Counter

+ +

Rendering: @RendererInfo.Name

+ +

Current count: @CounterTracker.CurrentCount

+ + + +@code { + protected override void OnInitialized() + { + if (!RendererInfo.IsInteractive) + { + CounterTracker.CurrentCount = 10; + } + } + + private void IncrementCount() + { + CounterTracker.IncrementCount(); + } +} +``` + +To use preceding component to demonstrate persisting the count of 10 in `CounterTracker.CurrentCount`, navigate to the component and refresh the browser, which triggers prerendering. When prerendering occurs, you briefly see indicate "`Static`" before displaying "`Server`" after final rendering. The counter starts at 10. + +## Use the `PersistentComponentState` service directly instead of the declarative model As an alternative to using the declarative model for persisting state with the `[PersistentState]` attribute, you can use the service directly, which offers greater flexibility for complex state persistence scenarios. Call to register a callback to persist the component state during prerendering. The state is retrieved when the component renders interactively. Make the call at the end of initialization code in order to avoid a potential race condition during app shutdown. @@ -268,10 +322,6 @@ When the component executes, `currentCount` is only set once during prerendering :::moniker-end -By initializing components with the same state used during prerendering, any expensive initialization steps are only executed once. The rendered UI also matches the prerendered UI, so no flicker occurs in the browser. - -The persisted prerendered state is transferred to the client, where it's used to restore the component state. During client-side rendering (CSR, `InteractiveWebAssembly`), the data is exposed to the browser and must not contain sensitive, private information. During interactive server-side rendering (interactive SSR, `InteractiveServer`), [ASP.NET Core Data Protection](xref:security/data-protection/introduction) ensures that the data is transferred securely. The `InteractiveAuto` render mode combines WebAssembly and Server interactivity, so it's necessary to consider data exposure to the browser, as in the CSR case. - :::moniker range=">= aspnetcore-10.0" ## Serialization extensibility for persistent component state diff --git a/aspnetcore/blazor/state-management/server.md b/aspnetcore/blazor/state-management/server.md index c7c96908419c..cb6ebfb2a4fb 100644 --- a/aspnetcore/blazor/state-management/server.md +++ b/aspnetcore/blazor/state-management/server.md @@ -51,6 +51,8 @@ An app can only persist *app state*. UIs can't be persisted, such as component i ## Circuit state persistence + + During server-side rendering, Blazor Web Apps can persist a user's session (circuit) state when the connection to the server is lost for an extended period of time or proactively paused, as long as a full-page refresh isn't triggered. This allows users to resume their session without losing unsaved work in the following scenarios: * Browser tab throttling diff --git a/aspnetcore/migration/60-70.md b/aspnetcore/migration/60-70.md index dd5161548ff8..8d11e8711c45 100644 --- a/aspnetcore/migration/60-70.md +++ b/aspnetcore/migration/60-70.md @@ -6,7 +6,7 @@ ms.author: wpickett ms.date: 10/14/2022 uid: migration/60-to-70 --- -# Migrate from ASP.NET Core in .NET 6 .NET 7 +# Migrate from ASP.NET Core in .NET 6 to .NET 7 This article explains how to update an existing ASP.NET Core in .NET 6 project to .NET 7. diff --git a/aspnetcore/security/anti-request-forgery.md b/aspnetcore/security/anti-request-forgery.md index 692c3532decd..f0c42c00909b 100644 --- a/aspnetcore/security/anti-request-forgery.md +++ b/aspnetcore/security/anti-request-forgery.md @@ -1,14 +1,14 @@ --- title: Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core +ai-usage: ai-assisted author: tdykstra -description: Discover how to prevent attacks against web apps where a malicious website can influence the interaction between a client browser and the app. -ms.author: tdykstra content_well_notification: AI-contribution +description: Discover how to prevent attacks against web apps where a malicious website can influence the interaction between a client browser and the app. monikerRange: '>= aspnetcore-3.1' +ms.author: tdykstra ms.custom: mvc ms.date: 11/16/2023 uid: security/anti-request-forgery -ai-usage: ai-assisted --- # Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core @@ -161,14 +161,13 @@ Calling in `Program.cs`: +Customize in the app's `Program` file: :::code language="csharp" source="anti-request-forgery/samples/6.x/AntiRequestForgerySample/Snippets/Program.cs" id="snippet_AddAntiforgeryOptions"::: -Set the antiforgery `Cookie` properties using the properties of the class, as shown in the following table. +Set the antiforgery cookie properties using the properties of the class, as shown in the following table. | Option | Description | | --- | --- | @@ -177,6 +176,20 @@ Set the antiforgery `Cookie` properties using the properties of the | The name of the header used by the antiforgery system. If `null`, the system considers only form data. | | | Specifies whether to suppress generation of the `X-Frame-Options` header. By default, the header is generated with a value of "SAMEORIGIN". Defaults to `false`. | +Some browsers don't allow insecure endpoints to set cookies with a 'secure' flag or overwrite cookies whose 'secure' flag is set (for more information, see [Deprecate modification of 'secure' cookies from non-secure origins](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-alone-01)). Since mixing secure and insecure endpoints is a common scenario in apps, ASP.NET Core relaxes the restriction on the secure policy on some cookies, such as the antiforgery cookie, by setting the cookie's to [`CookieSecurePolicy.None`](xref:Microsoft.AspNetCore.Http.CookieSecurePolicy). Even if a malicious user steals an antiforgery cookie, they also must steal the antiforgery token that's typically sent via a form field (more common) or a separate request header (less common) plus the authentication cookie. Cookies related to authentication or authorization use a stronger policy than [`CookieSecurePolicy.None`](xref:Microsoft.AspNetCore.Http.CookieSecurePolicy). + +Optionally, you can secure the antiforgery cookie in non-Development environments using Secure Sockets Layer (SSL), over HTTPS only, with the following property setting in the app's `Program` file: + +```csharp +if (!builder.Environment.IsDevelopment()) +{ + builder.Services.AddAntiforgery(o => + { + o.Cookie.SecurePolicy = CookieSecurePolicy.Always; + }); +} +``` + For more information, see . ## Generate antiforgery tokens with `IAntiforgery` @@ -481,15 +494,15 @@ With the Synchronizer Token Pattern, only the most recently loaded page contains * Only the most recently loaded tab contains a valid antiforgery token. * Requests made from previously loaded tabs fail with an error: `Antiforgery token validation failed. The antiforgery cookie token and request token do not match` - Consider alternative CSRF protection patterns if this poses an issue. +Consider alternative CSRF protection patterns if this poses an issue. ## Configure antiforgery with `AntiforgeryOptions` -Customize in `Program.cs`: +Customize in the app's `Program` file: :::code language="csharp" source="anti-request-forgery/samples/6.x/AntiRequestForgerySample/Snippets/Program.cs" id="snippet_AddAntiforgeryOptions"::: -Set the antiforgery `Cookie` properties using the properties of the class, as shown in the following table. +Set the antiforgery cookie properties using the properties of the class, as shown in the following table. | Option | Description | | --- | --- | @@ -498,6 +511,20 @@ Set the antiforgery `Cookie` properties using the properties of the | The name of the header used by the antiforgery system. If `null`, the system considers only form data. | | | Specifies whether to suppress generation of the `X-Frame-Options` header. By default, the header is generated with a value of "SAMEORIGIN". Defaults to `false`. | +Some browsers don't allow insecure endpoints to set cookies with a 'secure' flag or overwrite cookies whose 'secure' flag is set (for more information, see [Deprecate modification of 'secure' cookies from non-secure origins](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-alone-01)). Since mixing secure and insecure endpoints is a common scenario in apps, ASP.NET Core relaxes the restriction on the secure policy on some cookies, such as the antiforgery cookie, by setting the cookie's to [`CookieSecurePolicy.None`](xref:Microsoft.AspNetCore.Http.CookieSecurePolicy). Even if a malicious user steals an antiforgery cookie, they also must steal the antiforgery token that's typically sent via a form field (more common) or a separate request header (less common) plus the authentication cookie. Cookies related to authentication or authorization use a stronger policy than [`CookieSecurePolicy.None`](xref:Microsoft.AspNetCore.Http.CookieSecurePolicy). + +Optionally, you can secure the antiforgery cookie in non-Development environments using Secure Sockets Layer (SSL), over HTTPS only, with the following property setting in the app's `Program` file: + +```csharp +if (!builder.Environment.IsDevelopment()) +{ + builder.Services.AddAntiforgery(o => + { + o.Cookie.SecurePolicy = CookieSecurePolicy.Always; + }); +} +``` + For more information, see . ## Generate antiforgery tokens with `IAntiforgery` @@ -742,7 +769,7 @@ ASP.NET Core includes three [filters](xref:mvc/controllers/filters) for working * [AutoValidateAntiforgeryToken](xref:Microsoft.AspNetCore.Mvc.AutoValidateAntiforgeryTokenAttribute) * [IgnoreAntiforgeryToken](xref:Microsoft.AspNetCore.Mvc.IgnoreAntiforgeryTokenAttribute) -### Antiforgery with AddControllers +## Antiforgery with `AddControllers` Calling does ***not*** enable antiforgery tokens. must be called to have built-in antiforgery token support. @@ -753,15 +780,15 @@ With the Synchronizer Token Pattern, only the most recently loaded page contains * Only the most recently loaded tab contains a valid antiforgery token. * Requests made from previously loaded tabs fail with an error: `Antiforgery token validation failed. The antiforgery cookie token and request token do not match` - Consider alternative CSRF protection patterns if this poses an issue. +Consider alternative CSRF protection patterns if this poses an issue. ## Configure antiforgery with `AntiforgeryOptions` -Customize in `Program.cs`: +Customize in the app's `Program` file: :::code language="csharp" source="anti-request-forgery/samples/6.x/AntiRequestForgerySample/Snippets/Program.cs" id="snippet_AddAntiforgeryOptions"::: -Set the antiforgery `Cookie` properties using the properties of the class, as shown in the following table. +Set the antiforgery cookie properties using the properties of the class, as shown in the following table. | Option | Description | | --- | --- | @@ -770,6 +797,20 @@ Set the antiforgery `Cookie` properties using the properties of the | The name of the header used by the antiforgery system. If `null`, the system considers only form data. | | | Specifies whether to suppress generation of the `X-Frame-Options` header. By default, the header is generated with a value of "SAMEORIGIN". Defaults to `false`. | +Some browsers don't allow insecure endpoints to set cookies with a 'secure' flag or overwrite cookies whose 'secure' flag is set (for more information, see [Deprecate modification of 'secure' cookies from non-secure origins](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-alone-01)). Since mixing secure and insecure endpoints is a common scenario in apps, ASP.NET Core relaxes the restriction on the secure policy on some cookies, such as the antiforgery cookie, by setting the cookie's to [`CookieSecurePolicy.None`](xref:Microsoft.AspNetCore.Http.CookieSecurePolicy). Even if a malicious user steals an antiforgery cookie, they also must steal the antiforgery token that's typically sent via a form field (more common) or a separate request header (less common) plus the authentication cookie. Cookies related to authentication or authorization use a stronger policy than [`CookieSecurePolicy.None`](xref:Microsoft.AspNetCore.Http.CookieSecurePolicy). + +Optionally, you can secure the antiforgery cookie in non-Development environments using Secure Sockets Layer (SSL), over HTTPS only, with the following property setting in the app's `Program` file: + +```csharp +if (!builder.Environment.IsDevelopment()) +{ + builder.Services.AddAntiforgery(o => + { + o.Cookie.SecurePolicy = CookieSecurePolicy.Always; + }); +} +``` + For more information, see . ## Generate antiforgery tokens with `IAntiforgery` @@ -1034,7 +1075,7 @@ services.AddAntiforgery(options => }); ``` -Set the antiforgery `Cookie` properties using the properties of the class, as shown in the following table. +Set the antiforgery cookie properties using the properties of the class, as shown in the following table. | Option | Description | | --- | --- | @@ -1043,6 +1084,42 @@ Set the antiforgery `Cookie` properties using the properties of the | The name of the header used by the antiforgery system. If `null`, the system considers only form data. | | | Specifies whether to suppress generation of the `X-Frame-Options` header. By default, the header is generated with a value of "SAMEORIGIN". Defaults to `false`. | +Some browsers don't allow insecure endpoints to set cookies with a 'secure' flag or overwrite cookies whose 'secure' flag is set (for more information, see [Deprecate modification of 'secure' cookies from non-secure origins](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-alone-01)). Since mixing secure and insecure endpoints is a common scenario in apps, ASP.NET Core relaxes the restriction on the secure policy on some cookies, such as the antiforgery cookie, by setting the cookie's to [`CookieSecurePolicy.None`](xref:Microsoft.AspNetCore.Http.CookieSecurePolicy). Even if a malicious user steals an antiforgery cookie, they also must steal the antiforgery token that's typically sent via a form field (more common) or a separate request header (less common) plus the authentication cookie. Cookies related to authentication or authorization use a stronger policy than [`CookieSecurePolicy.None`](xref:Microsoft.AspNetCore.Http.CookieSecurePolicy). + +Optionally, you can secure the antiforgery cookie in non-Development environments using Secure Sockets Layer (SSL), over HTTPS only, with the following property setting in the app's `Startup` class: + +```csharp +public class Startup +{ + public Startup(IConfiguration configuration, IHostEnvironment environment) + { + Configuration = configuration; + Environment = environment; + } + + public IConfiguration Configuration { get; } + public IHostEnvironment Environment { get; } + + public void ConfigureServices(IServiceCollection services) + { + // Other services are registered here + + if (!Environment.IsDevelopment()) + { + services.AddAntiforgery(o => + { + o.Cookie.SecurePolicy = CookieSecurePolicy.Always; + }); + } + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + // Request processing pipeline + } +} +``` + For more information, see . ## Configure antiforgery features with IAntiforgery diff --git a/aspnetcore/security/authentication/configure-jwt-bearer-authentication.md b/aspnetcore/security/authentication/configure-jwt-bearer-authentication.md index 61252a1a47e8..23a4e5831083 100644 --- a/aspnetcore/security/authentication/configure-jwt-bearer-authentication.md +++ b/aspnetcore/security/authentication/configure-jwt-bearer-authentication.md @@ -180,7 +180,7 @@ APIs often need to accommodate access tokens from various issuers. Supporting mu ### Forcing the bearer authentication - can be used to require authentication for all requests even to endpoints without an `[Authorize]` attribute. configures the policy used for endpoints with the `[Authorize]` attribute and already defaults to requiring authenticated users. See the [require authenticated users documentation](/aspnet/core/security/authorization/secure-data#require-authenticated-users) for more details. + can be used to require authentication for all requests even to endpoints without an `[Authorize]` attribute. configures the policy used for endpoints with the `[Authorize]` attribute and already defaults to requiring authenticated users. See the [require authenticated users documentation](/aspnet/core/security/authorization/secure-data#require-authenticated-users) for more details. ```csharp var requireAuthPolicy = new AuthorizationPolicyBuilder() @@ -188,7 +188,7 @@ var requireAuthPolicy = new AuthorizationPolicyBuilder() .Build(); builder.Services.AddAuthorizationBuilder() - .SetDefaultPolicy(requireAuthPolicy); + .SetFallbackPolicy(requireAuthPolicy); ``` The attribute can also be used to force the authentication. If multiple schemes are used, the bearer scheme generally needs to be set as the default authentication scheme or specified via `[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme])`. diff --git a/aspnetcore/security/authentication/windowsauth.md b/aspnetcore/security/authentication/windowsauth.md index 26ea1c51bd92..1b853fa969ad 100644 --- a/aspnetcore/security/authentication/windowsauth.md +++ b/aspnetcore/security/authentication/windowsauth.md @@ -5,8 +5,9 @@ description: Learn how to configure Windows Authentication in ASP.NET Core for I monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.custom: mvc -ms.date: 11/15/2021 +ms.date: 08/10/2025 uid: security/authentication/windowsauth +ms.ai: assisted --- # Configure Windows Authentication in ASP.NET Core @@ -18,8 +19,49 @@ Windows Authentication (also known as Negotiate, Kerberos, or NTLM authenticatio Windows Authentication relies on the operating system to authenticate users of ASP.NET Core apps. Windows Authentication is used for servers that run on a corporate network using Active Directory domain identities or Windows accounts to identify users. Windows Authentication is best suited to intranet environments where users, client apps, and web servers belong to the same Windows domain. +## When to use Windows Authentication + +Windows Authentication is suitable for web applications that operate within an organization's private internal network, accessible only to employees (and other authorized users) within the same network. The user management is done within Active Directory (AD), and users use their existing Windows domain account to authenticate. + +Windows Authentication provides several benefits for intranet applications: + +* **Seamless user experience** - Users are automatically authenticated based on their active Windows session, or are prompted to enter their Windows credentials via a standard browser dialog box. +* **Integration with Active Directory** - Leverages existing Windows infrastructure and security policies, including user groups, account lockouts, and multi-factor authentication (MFA). +* **Secure credential handling** - Authentication is handled through secure protocols like Kerberos, with no need to manage separate user credentials. +* **Role-based authorization** - Applications can access user and group information from Active Directory, enabling role-based access control (RBAC) within the application. +* **Reduced administrative overhead** - No need to maintain a separate user database or credential management system. + +This makes Windows Authentication ideal for organizations that want to make use of their existing Windows infrastructure, such as intranet portals. + > [!NOTE] -> Windows Authentication isn't supported with HTTP/2. Authentication challenges can be sent on HTTP/2 responses, but the client must downgrade to HTTP/1.1 before authenticating. +> Windows Authentication isn't supported with HTTP/2. While authentication challenges can be sent over HTTP/2 responses, the client must downgrade to HTTP/1.1 to complete the authentication process. This is a protocol limitation, not a deprecation of Windows Authentication. Once authenticated, normal HTTP/2 communication can resume for subsequent requests. + +For public-facing applications Windows Authentication isn't recommended due to security and usability concerns. +These reasons include: +* Windows Authentication is best kept internal to protect Active Directory, exposing it outside an internal network introduces security risks. +* External users don't have Windows domain accounts. +* It's complex to configure the necessary network infrastructure securely, and firewalls or proxies may interfere with the authentication process. +* It's not cross-platform and doesn't provide customization options for designs and user experiences. + +### Alternatives for different scenarios + +Depending on your application requirements, consider these alternatives: + +**For public-facing applications:** + +* [OpenID Connect](xref:security/how-to-choose-identity) with external identity providers +* ASP.NET Core Identity with local user accounts () +* Azure Active Directory (AAD) for Microsoft 365 environments + +**For mixed environments** with both intranet and external users: + +* Active Directory Federation Services (ADFS) with OpenID Connect +* Azure Active Directory with hybrid configuration + +**For corporate environments using modern authentication:** + +* Azure Active Directory with single sign-on +* SAML-based solutions with third-party identity providers ## Proxy and load balancer scenarios @@ -267,8 +309,49 @@ Windows Authentication (also known as Negotiate, Kerberos, or NTLM authenticatio Windows Authentication relies on the operating system to authenticate users of ASP.NET Core apps. You can use Windows Authentication when your server runs on a corporate network using Active Directory domain identities or Windows accounts to identify users. Windows Authentication is best suited to intranet environments where users, client apps, and web servers belong to the same Windows domain. +## When to use Windows Authentication + +Windows Authentication is suitable for web applications that operate within an organization's private internal network, accessible only to employees (and other authorized users) within the same network. The user management is done within Active Directory (AD), and users use their existing Windows domain account to authenticate. + +Windows Authentication provides several benefits for intranet applications: + +* **Seamless user experience** - Users are automatically authenticated based on their active Windows session, or are prompted to enter their Windows credentials via a standard browser dialog box. +* **Integration with Active Directory** - Leverages existing Windows infrastructure and security policies, including user groups, account lockouts, and multi-factor authentication (MFA). +* **Secure credential handling** - Authentication is handled through secure protocols like Kerberos, with no need to manage separate user credentials. +* **Role-based authorization** - Applications can access user and group information from Active Directory, enabling role-based access control (RBAC) within the application. +* **Reduced administrative overhead** - No need to maintain a separate user database or credential management system. + +This makes Windows Authentication ideal for organizations that want to make use of their existing Windows infrastructure, such as intranet portals. + > [!NOTE] -> Windows Authentication isn't supported with HTTP/2. Authentication challenges can be sent on HTTP/2 responses, but the client must downgrade to HTTP/1.1 before authenticating. +> Windows Authentication isn't supported with HTTP/2. While authentication challenges can be sent over HTTP/2 responses, the client must downgrade to HTTP/1.1 to complete the authentication process. This is a protocol limitation, not a deprecation of Windows Authentication. Once authenticated, normal HTTP/2 communication can resume for subsequent requests. + +For public-facing applications Windows Authentication isn't recommended due to security and usability concerns. +These reasons include: +* Windows Authentication is best kept internal to protect Active Directory, exposing it outside an internal network introduces security risks. +* External users don't have Windows domain accounts. +* It's complex to configure the necessary network infrastructure securely, and firewalls or proxies may interfere with the authentication process. +* It's not cross-platform and doesn't provide customization options for designs and user experiences. + +### Alternatives for different scenarios + +Depending on your application requirements, consider these alternatives: + +**For public-facing applications:** + +* [OpenID Connect](xref:security/how-to-choose-identity) with external identity providers +* ASP.NET Core Identity with local user accounts () +* Azure Active Directory (AAD) for Microsoft 365 environments + +**For mixed environments** with both intranet and external users: + +* Active Directory Federation Services (ADFS) with OpenID Connect +* Azure Active Directory with hybrid configuration + +**For corporate environments using modern authentication:** + +* Azure Active Directory with single sign-on +* SAML-based solutions with third-party identity providers ## Proxy and load balancer scenarios diff --git a/aspnetcore/security/data-protection/configuration/overview.md b/aspnetcore/security/data-protection/configuration/overview.md index 322bad0dc593..88aada6d3902 100644 --- a/aspnetcore/security/data-protection/configuration/overview.md +++ b/aspnetcore/security/data-protection/configuration/overview.md @@ -5,7 +5,7 @@ description: Learn how to configure Data Protection in ASP.NET Core. monikerRange: '>= aspnetcore-3.1' ms.author: tdykstra ms.custom: mvc -ms.date: 06/11/2025 +ms.date: 10/08/2025 uid: security/data-protection/configuration/overview --- # Configure ASP.NET Core Data Protection @@ -31,8 +31,8 @@ For these scenarios, the Data Protection system offers a rich configuration API. The following NuGet packages are required for the Data Protection extensions used in this article: -* [Azure.Extensions.AspNetCore.DataProtection.Blobs](https://www.nuget.org/packages/Azure.Extensions.AspNetCore.DataProtection.Blobs) -* [Azure.Extensions.AspNetCore.DataProtection.Keys](https://www.nuget.org/packages/Azure.Extensions.AspNetCore.DataProtection.Keys) +* [`Azure.Extensions.AspNetCore.DataProtection.Blobs`](https://www.nuget.org/packages/Azure.Extensions.AspNetCore.DataProtection.Blobs) +* [`Azure.Extensions.AspNetCore.DataProtection.Keys`](https://www.nuget.org/packages/Azure.Extensions.AspNetCore.DataProtection.Keys) ## Protect keys with Azure Key Vault (`ProtectKeysWithAzureKeyVault`) @@ -44,7 +44,7 @@ az login For more information, see [Sign-in to Azure using developer tooling](/dotnet/azure/sdk/authentication/local-development-dev-accounts#sign-in-to-azure-using-developer-tooling). -When establishing the key vault in the Entra or Azure portal: +When [establishing the key vault in the Entra or Azure portal](/azure/key-vault/general/quick-create-portal): * Configure the key vault to use Azure role-based access control (RABC). If you aren't operating on an [Azure Virtual Network](/azure/virtual-network/virtual-networks-overview), including for local development and testing, confirm that public access on the **Networking** step is **enabled** (checked). Enabling public access only exposes the key vault endpoint. Authenticated accounts are still required for access. @@ -63,6 +63,8 @@ To configure the Azure Key Vault provider, call one of the , passing `true` for `enableLogForwarding`, to create and wire up the logging infrastructure. +To create a key in the Azure portal, see [Quickstart: Set and retrieve a key from Azure Key Vault using the Azure portal](/azure/key-vault/keys/quick-create-portal). Give the key at least `Get`, `Unwrap Key`, and `Wrap Key` permissions. Record the key identifier for use with the app's configuration. If you plan to enable automatic rotation of the key vault key, record the *versionless* key identifier, where no key GUID is placed at the end of the identifier (example: `https://contoso.vault.azure.net/keys/data-protection`). + In the `Program` file where services are registered: ```csharp @@ -100,7 +102,7 @@ builder.Services.AddDataProtection() `{BLOB URI}`: Full URI to the key file. The URI is generated by Azure Storage when you create the key file. Do not use a SAS. -`{KEY IDENTIFIER}`: Azure Key Vault key identifier used for key encryption. An access policy allows the application to access the key vault with `Get`, `Unwrap Key`, and `Wrap Key` permissions. The version of the key is obtained from the key in the Entra or Azure portal after it's created. If you enable automatic rotation of the key vault key, make sure that you use a versionless key identifier in the app's key vault configuration, where no key GUID is placed at the end of the identifier (example: `https://contoso.vault.azure.net/keys/data-protection`). +`{KEY IDENTIFIER}`: Azure Key Vault key identifier used for key encryption. An access policy allows the application to access the key vault with `Get`, `Unwrap Key`, and `Wrap Key` permissions. The version of the key is obtained from the key in the Entra or Azure portal after it's created. If you enable automatic rotation of the key vault key, make sure that you use a *versionless* key identifier in the app's key vault configuration, where no key GUID is placed at the end of the identifier (example: `https://contoso.vault.azure.net/keys/data-protection`). For an app to communicate and authorize itself with Azure Key Vault, the [`Azure.Identity` NuGet package](https://www.nuget.org/packages/Azure.Identity/) must be referenced by the app. @@ -380,7 +382,7 @@ az login For more information, see [Sign-in to Azure using developer tooling](/dotnet/azure/sdk/authentication/local-development-dev-accounts#sign-in-to-azure-using-developer-tooling). -When establishing the key vault in the Entra or Azure portal: +When [establishing the key vault in the Entra or Azure portal](/azure/key-vault/general/quick-create-portal): * Configure the key vault to use Azure role-based access control (RABC). If you aren't operating on an [Azure Virtual Network](/azure/virtual-network/virtual-networks-overview), including for local development and testing, confirm that public access on the **Networking** step is **enabled** (checked). Enabling public access only exposes the key vault endpoint. Authenticated accounts are still required for access. @@ -399,6 +401,8 @@ To configure the Azure Key Vault provider, call one of the , passing `true` for `enableLogForwarding`, to create and wire up the logging infrastructure. +To create a key in the Azure portal, see [Quickstart: Set and retrieve a key from Azure Key Vault using the Azure portal](/azure/key-vault/keys/quick-create-portal). Give the key at least `Get`, `Unwrap Key`, and `Wrap Key` permissions. Record the key identifier for use with the app's configuration. If you plan to enable automatic rotation of the key vault key, record the *versionless* key identifier, where no key GUID is placed at the end of the identifier (example: `https://contoso.vault.azure.net/keys/data-protection`). + In the `Program` file where services are registered: ```csharp @@ -436,7 +440,7 @@ services.AddDataProtection() `{BLOB URI}`: Full URI to the key file. The URI is generated by Azure Storage when you create the key file. Do not use a SAS. -`{KEY IDENTIFIER}`: Azure Key Vault key identifier used for key encryption. An access policy allows the application to access the key vault with `Get`, `Unwrap Key`, and `Wrap Key` permissions. The version of the key is obtained from the key in the Entra or Azure portal after it's created. If you enable automatic rotation of the key vault key, make sure that you use a versionless key identifier in the app's key vault configuration, where no key GUID is placed at the end of the identifier (example: `https://contoso.vault.azure.net/keys/data-protection`). +`{KEY IDENTIFIER}`: Azure Key Vault key identifier used for key encryption. An access policy allows the application to access the key vault with `Get`, `Unwrap Key`, and `Wrap Key` permissions. The version of the key is obtained from the key in the Entra or Azure portal after it's created. If you enable automatic rotation of the key vault key, make sure that you use a *versionless* key identifier in the app's key vault configuration, where no key GUID is placed at the end of the identifier (example: `https://contoso.vault.azure.net/keys/data-protection`). For an app to communicate and authorize itself with Azure Key Vault, the [`Azure.Identity` NuGet package](https://www.nuget.org/packages/Azure.Identity/) must be referenced by the app.