Skip to content

v11 update: Negotiate authentication uses TLS channel binding #37710

Description

@wadepickett

Note

This is an AI-assisted coverage analysis created by wadepickett.

Target repository: dotnet/AspNetCore.Docs
Analyzed at commit: 4986136881f2bbf1879f10106467769df5a49932
Product source verified at: dotnet/aspnetcore @ 1fcd7ef305697a1888f3ede076010350ae9f4f8d
Source release note: Negotiate authentication uses TLS channel binding


🎯 Goal

Tell a reader of the Windows Authentication article that, on Kestrel over HTTPS, Negotiate now cryptographically binds the Kerberos/NTLM exchange to the TLS channel automatically — a security hardening (Extended Protection for Authentication) they get for free in .NET 11. The Kestrel section of security/authentication/windowsauth.md says nothing about it today, and the one channel-binding note that does exist in the article is about a different server (HTTP.sys) and a different, opt-in mechanism, so leaving this undocumented invites readers to conflate the two.

This is a behavior change with no new public API. Searching the docset for a new type or member finds nothing; the feature element is the behavior itself, verified against product source.


✅ Coverage status summary

Legend: ✅ already documented · ✏️ update needed · 🟣 could not determine

# Feature element from What's New Status Where
1 Negotiate on Kestrel uses the TLS endpoint channel binding token for HTTPS connections ✏️ 1. Update — security/authentication/windowsauth.md L173–L177 (Kestrel section)
2 The handler supplies the token to the Kerberos/NTLM exchange and retains it across multi-round authentication ✏️ 1. Update — same note
3 No configuration required; non-HTTPS connections and HTTPS connections without a channel binding token keep the previous behavior ✏️ 1. Update — same note
— Existing article CBT note applies to this feature ✅ (distinct) The L265–L266 note is HTTP.sys-specific (opt-in EnableCBTHardening AppContext switch) — it does not cover the new Kestrel behavior. Must be kept distinct.

🔢 Version applicability

Applies to: CURRENT-ONLY
Target moniker: >= aspnetcore-11.0
Earlier versions affected: None — automatic TLS channel binding for Negotiate on Kestrel is new in .NET 11.

Article monikerRange Moniker state
security/authentication/windowsauth.md '>= aspnetcore-3.1' (front matter) State D — the insertion point (L175, Kestrel section) sits inside the broader >= aspnetcore-6.0 body zone (L16–L313). A full four-directive split is required: close >= aspnetcore-6.0, open >= aspnetcore-11.0, add the note, close it, reopen >= aspnetcore-6.0.

The article's body has exactly two zones — >= aspnetcore-6.0 (L16–L313) and < aspnetcore-6.0 (L315–L619). There are no tab groups anywhere in the file, so the split carries no tab-nesting hazard.


📋 Coverage gap summary

The Kestrel section opens at L169 and runs through a WARNING about proxy connection affinity (L173–L174) and a NOTE about native Windows Authentication detection (L176–L177), then into the Program.cs sample — with no mention of channel binding. A developer hardening a Kestrel-hosted intranet app against NTLM relay has no way to learn from this article that .NET 11 already does it for them on HTTPS. The only channel-binding text in the article, at L265–L266, sits in the HTTP.sys section and describes the opt-in Microsoft.AspNetCore.Server.HttpSys.EnableCBTHardening AppContext switch — a separate feature on a separate server that is off by default. Presenting the two without distinction would mislead.

Feature announced in What's New:

Negotiate authentication on Kestrel uses the TLS endpoint channel binding token for HTTPS connections. The authentication handler supplies the token to the underlying Kerberos or NTLM exchange and retains it across multi-round authentication.

No configuration changes are required. Non-HTTPS connections and HTTPS connections where a channel binding token isn't available continue to use the existing behavior.

Product source confirms the mechanism: the Negotiate handler reads the token from the connection's TLS feature — ITlsConnectionFeature.TryGetChannelBindingBytes(ChannelBindingKind.Endpoint, out …) — and wraps it for the Kerberos/NTLM exchange. It is automatic and unconditional for HTTPS connections that expose an endpoint CBT; there is no option to configure.

Breaking change: No — additive hardening with a documented fallback to prior behavior.


📁 Affected files

Item Path Lines Section
1. security/authentication/windowsauth.md 175 (between L174 and L176) Kestrel

Target article uids: security/authentication/windowsauth


📝 Proposed changes

✏️ 1. Update — security/authentication/windowsauth.md, add a channel-binding note to the Kestrel section (State D split at line 175)

Applies to: >= aspnetcore-11.0
Location: Lines 173–177, between the Kestrel WARNING block (ends L174) and the "native Windows Authentication detection" NOTE (starts L176).

Before (lines 173–177):

> [!WARNING]
> Credentials can be persisted across requests on a connection. *Negotiate authentication must not be used with proxies unless the proxy maintains a 1:1 connection affinity (a persistent connection) with Kestrel.*

> [!NOTE]
> The Negotiate handler detects if the underlying server supports Windows Authentication natively and if it is enabled. If the server supports Windows Authentication but it is disabled, an error is thrown asking you to enable the server implementation. When Windows Authentication is enabled in the server, the Negotiate handler transparently forwards authentication requests to it.

After:

> [!WARNING]
> Credentials can be persisted across requests on a connection. *Negotiate authentication must not be used with proxies unless the proxy maintains a 1:1 connection affinity (a persistent connection) with Kestrel.*

:::moniker-end

:::moniker range=">= aspnetcore-11.0"

> [!NOTE]
> Beginning with .NET 11, Negotiate authentication on Kestrel binds the authentication exchange to the connection using the [TLS endpoint channel binding token](/dotnet/api/system.security.authentication.extendedprotection.channelbinding) for HTTPS connections. The handler supplies the token to the underlying Kerberos or NTLM exchange and retains it across multi-round authentication, which helps mitigate NTLM relay and man-in-the-middle attacks. No configuration is required. Non-HTTPS connections, and HTTPS connections where a channel binding token isn't available, continue to use the previous behavior.

:::moniker-end

:::moniker range=">= aspnetcore-6.0"

> [!NOTE]
> The Negotiate handler detects if the underlying server supports Windows Authentication natively and if it is enabled. If the server supports Windows Authentication but it is disabled, an error is thrown asking you to enable the server implementation. When Windows Authentication is enabled in the server, the Negotiate handler transparently forwards authentication requests to it.

Rationale: The behavior is Kestrel-specific (on HTTP.sys, Windows Authentication is handled in kernel mode, not by the Negotiate handler), so the Kestrel section is the correct home. The note is scoped >= aspnetcore-11.0 because the automatic binding is new in .NET 11, and the surrounding content must remain >= aspnetcore-6.0 — hence the four-directive split. The wording deliberately parallels, but does not merge with, the HTTP.sys CBT-hardening note at L265–L266 so readers don't confuse the automatic Kestrel behavior with the opt-in HTTP.sys AppContext switch.


✅ 2. Update — TOC

No TOC change required. The edit adds a note to an article already in the TOC.


✅ Action plan

  1. Confirm the coverage status summary — element 1 is a genuine gap; the L265–L266 note is HTTP.sys-only and must stay distinct.
  2. Apply change 1 as a State D four-directive split. After editing, verify moniker balance: the file should have 4 :::moniker range= openers and 4 :::moniker-end closers (up from 2 and 2), with the reopened >= aspnetcore-6.0 range copied character-for-character.
  3. Confirm the /dotnet/api/system.security.authentication.extendedprotection.channelbinding link resolves; if a more specific conceptual target is preferred, substitute it.
  4. Build and confirm the new NOTE renders only under the .NET 11 selector while the detection NOTE renders for 6.0+.
  5. Resolve any OpenPublishing.Build warnings.

⚠️ Review considerations

  • 🟣 Depth of cross-reference to ITlsConnectionFeature.TryGetChannelBindingBytes. The enabling server-side API (RFC 5929 endpoint CBT exposure) is documented for HTTP.sys in breaking-changes/11/httpsys-channel-binding-token-enabled.md. Whether the Kestrel note should cross-link that breaking-change article (different server, but the same underlying ITlsConnectionFeature API) is an editorial call; the proposed note keeps it simple and omits the link to avoid implying the HTTP.sys opt-out applies to Kestrel.
  • Out of scope: the corresponding Miscellaneous-area feature that exposes ITlsConnectionFeature.TryGetChannelBindingBytes to application code — not yet analyzed at the time of filing; this issue covers only the Negotiate-on-Kestrel consumer behavior. If that feature is filed later, cross-link the two.

🔗 References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions