Skip to content

DownstreamApi: ignore caller-supplied reserved or duplicate headers in ExtraHeaderParameters#3793

Merged
bgavrilMS merged 4 commits intomasterfrom
iinglese/downstreamapi-header-handling
May 1, 2026
Merged

DownstreamApi: ignore caller-supplied reserved or duplicate headers in ExtraHeaderParameters#3793
bgavrilMS merged 4 commits intomasterfrom
iinglese/downstreamapi-header-handling

Conversation

@iNinja
Copy link
Copy Markdown
Contributor

@iNinja iNinja commented Apr 24, 2026

Description

Hardens header handling in DownstreamApi.cs so that headers supplied via DownstreamApiOptions.ExtraHeaderParameters cannot override headers the library is responsible for setting itself.

Behaviour change

When iterating ExtraHeaderParameters to apply caller-supplied headers to the outbound HttpRequestMessage:

  • Headers whose names match a reserved set (e.g. Authorization, Proxy-Authorization, Host, Content-Length, Transfer-Encoding, Connection, Upgrade, Expect, plus the Sec- and Proxy- prefixes) are skipped. Comparison is case-insensitive.
  • Headers that duplicate a name the library has already set on the request are skipped.

Skipped entries are logged via existing ILogger plumbing (ReservedHeaderIgnored, DuplicateHeaderIgnored) at Warning level so operators can spot misconfigurations. The request is otherwise sent normally — no exception is thrown.

What's included

  • src/Microsoft.Identity.Web.DownstreamApi/ReservedHeaderNames.cs — new internal helper (IsReserved(string)) with the reserved name list and prefix checks.
  • src/Microsoft.Identity.Web.DownstreamApi/DownstreamApi.cs — skip + log in the ExtraHeaderParameters loop.
  • src/Microsoft.Identity.Web.DownstreamApi/Logging/Logging.cs — two new log event definitions.
  • tests/Microsoft.Identity.Web.Test/DownstreamWebApiSupport/DownstreamApiTests.cs — five new tests covering reserved-name skip (case variants), prefix skip, duplicate skip, and the happy path that benign headers still flow through.
  • InternalAPI.Unshipped.txt updates for the affected packages.

Notes for reviewers

  • No public API change; reserved-name handling is internal and additive.
  • Behaviour is on by default — no opt-in flag. Callers relying on overriding Authorization (or other reserved names) via ExtraHeaderParameters will see those entries silently dropped with a warning log; the recommended path remains the existing AcquireTokenOptions / AuthenticationScheme plumbing.
  • Defaults are conservative; the reserved set deliberately mirrors what HttpClient itself treats as restricted.

…n ExtraHeaderParameters

When ExtraHeaderParameters contains an entry whose name is reserved for
the library (Authorization, Cookie, Host, X-Forwarded-*, X-Original-URL,
X-MS-CLIENT-PRINCIPAL*, X-MS-TOKEN-AAD-*) or is already present on the
outgoing request (e.g. Accept set via AcceptHeader), the entry is now
skipped and a warning is logged instead of being added alongside the
library-set value.

Adds ReservedHeaderNames helper and two LoggerMessage entries
(EventIds 102, 103). All new types and members are internal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pmaytak
Copy link
Copy Markdown
Collaborator

pmaytak commented Apr 30, 2026

@copilot resolve the merge conflicts in this pull request

…api-header-handling

# Conflicts:
#	src/Microsoft.Identity.Web.DownstreamApi/PublicAPI/net10.0/InternalAPI.Unshipped.txt
#	src/Microsoft.Identity.Web.DownstreamApi/PublicAPI/net462/InternalAPI.Unshipped.txt
#	src/Microsoft.Identity.Web.DownstreamApi/PublicAPI/net472/InternalAPI.Unshipped.txt
#	src/Microsoft.Identity.Web.DownstreamApi/PublicAPI/net8.0/InternalAPI.Unshipped.txt
#	src/Microsoft.Identity.Web.DownstreamApi/PublicAPI/net9.0/InternalAPI.Unshipped.txt
#	src/Microsoft.Identity.Web.DownstreamApi/PublicAPI/netstandard2.0/InternalAPI.Unshipped.txt

Co-authored-by: pmaytak <34331512+pmaytak@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 30, 2026

@copilot resolve the merge conflicts in this pull request

Resolved in commit 461d18d. The conflicts were in the per-TFM InternalAPI.Unshipped.txt files under src/Microsoft.Identity.Web.DownstreamApi/PublicAPI/ — master's API File Cleanup (#3798) deleted those files as part of consolidating to a NetCore/NetFramework structure, while this branch had modified them. Resolved by accepting the deletion (the new csproj structure no longer references per-TFM internal API files).

Copilot AI requested a review from pmaytak April 30, 2026 01:30
This was referenced May 4, 2026
github-actions Bot pushed a commit to EelcoLos/nx-tinkering that referenced this pull request May 5, 2026
Updated
[Microsoft.Identity.Web](https://github.com/AzureAD/microsoft-identity-web)
from 4.8.0 to 4.9.0.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.Identity.Web's
releases](https://github.com/AzureAD/microsoft-identity-web/releases)._

## 4.9.0

### New features
- **Sidecar: per-route override gating.** New `Sidecar:AllowOverrides`
configuration section provides explicit, per-route control over whether
`optionsOverride.*` query-string parameters are honored. Authenticated
routes default to allowing overrides (preserving existing behavior);
unauthenticated routes default to rejecting them.
`optionsOverride.BaseUrl` is unconditionally rejected on all routes as a
hardening measure. See
[#​3794](AzureAD/microsoft-identity-web#3794).

### Bug fixes
- Fix `AccountController.Challenge` redirect URI validation to reject
percent-encoded protocol-relative bypasses (`%2F%2F`, `%5C%2F`, etc.)
that could be decoded by misconfigured reverse proxies. See
[#​3792](AzureAD/microsoft-identity-web#3792).

### Behavior changes
- **DownstreamApi: reserved header filtering.** Headers supplied via
`DownstreamApiOptions.ExtraHeaderParameters` whose names match reserved
HTTP headers (`Authorization`, `Host`, `Content-Length`,
`Proxy-Authorization`, `Sec-*`, `Proxy-*`, etc.) or duplicate a header
the library already set are now silently skipped. A warning-level log
entry (`ReservedHeaderIgnored` / `DuplicateHeaderIgnored`) is emitted so
operators can spot misconfigurations. No exception is thrown. See
[#​3793](AzureAD/microsoft-identity-web#3793).

### Dependencies updates
- **Update Azure.Identity 1.11.4 → 1.17.2 and establish
Microsoft.Extensions.\* 8.0.x minimum on older TFMs.** Azure.Identity
1.17.2 (sovereign-cloud fixes) pulls in Azure.Core 1.50.0, which
introduces a transitive dependency on
`Microsoft.Extensions.DependencyInjection.Abstractions` 8.0.2 on
non-framework-coupled TFMs (net462, net472, netstandard2.0). This caused
a `CS0433` type collision with the previously-pinned
`Microsoft.Extensions.DependencyInjection` 2.1.0. Rather than patch
individual packages, the entire `Microsoft.Extensions.*` stack on these
older TFMs has been bumped to 8.0.x, closing several 5-year version gaps
and aligning with the net8.0 baseline. **If your application targets
net462, net472, or netstandard2.0**, your resolved
`Microsoft.Extensions.*` versions will increase (e.g., `Extensions.Http`
3.1.3 → 8.0.0, `Extensions.DependencyInjection` 2.1.0 → 8.0.0,
`Extensions.Caching.Memory` 2.1.0/6.0.2 → 8.0.1). Applications already
targeting net8.0+ are unaffected. See
[#​3787](AzureAD/microsoft-identity-web#3787).
- Bump `System.Text.Json` 8.0.5 → 8.0.6 (CVE-2024-43485). See
[#​3787](AzureAD/microsoft-identity-web#3787).
- Bump `Microsoft.AspNetCore.DataProtection` to 10.0.7 for CVE fix on
net10.0. See
[#​3796](AzureAD/microsoft-identity-web#3796).
- Bump `OpenTelemetry.Exporter.OpenTelemetryProtocol` 1.14.0 → 1.15.3.
See
[#​3788](AzureAD/microsoft-identity-web#3788).

**Full Changelog**:
AzureAD/microsoft-identity-web@4.8.0...4.9.0

Commits viewable in [compare
view](AzureAD/microsoft-identity-web@4.8.0...4.9.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.Identity.Web&package-manager=nuget&previous-version=4.8.0&new-version=4.9.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Eelco Los <5102501+EelcoLos@users.noreply.github.com>
gunndabad added a commit to DFE-Digital/teaching-record-system that referenced this pull request May 6, 2026
#3354)

Updated
[Microsoft.Identity.Web.GraphServiceClientBeta](https://github.com/AzureAD/microsoft-identity-web)
from 4.8.0 to 4.9.0.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.Identity.Web.GraphServiceClientBeta's
releases](https://github.com/AzureAD/microsoft-identity-web/releases)._

## 4.9.0

### New features
- **Sidecar: per-route override gating.** New `Sidecar:AllowOverrides`
configuration section provides explicit, per-route control over whether
`optionsOverride.*` query-string parameters are honored. Authenticated
routes default to allowing overrides (preserving existing behavior);
unauthenticated routes default to rejecting them.
`optionsOverride.BaseUrl` is unconditionally rejected on all routes as a
hardening measure. See
[#​3794](AzureAD/microsoft-identity-web#3794).

### Bug fixes
- Fix `AccountController.Challenge` redirect URI validation to reject
percent-encoded protocol-relative bypasses (`%2F%2F`, `%5C%2F`, etc.)
that could be decoded by misconfigured reverse proxies. See
[#​3792](AzureAD/microsoft-identity-web#3792).

### Behavior changes
- **DownstreamApi: reserved header filtering.** Headers supplied via
`DownstreamApiOptions.ExtraHeaderParameters` whose names match reserved
HTTP headers (`Authorization`, `Host`, `Content-Length`,
`Proxy-Authorization`, `Sec-*`, `Proxy-*`, etc.) or duplicate a header
the library already set are now silently skipped. A warning-level log
entry (`ReservedHeaderIgnored` / `DuplicateHeaderIgnored`) is emitted so
operators can spot misconfigurations. No exception is thrown. See
[#​3793](AzureAD/microsoft-identity-web#3793).

### Dependencies updates
- **Update Azure.Identity 1.11.4 → 1.17.2 and establish
Microsoft.Extensions.\* 8.0.x minimum on older TFMs.** Azure.Identity
1.17.2 (sovereign-cloud fixes) pulls in Azure.Core 1.50.0, which
introduces a transitive dependency on
`Microsoft.Extensions.DependencyInjection.Abstractions` 8.0.2 on
non-framework-coupled TFMs (net462, net472, netstandard2.0). This caused
a `CS0433` type collision with the previously-pinned
`Microsoft.Extensions.DependencyInjection` 2.1.0. Rather than patch
individual packages, the entire `Microsoft.Extensions.*` stack on these
older TFMs has been bumped to 8.0.x, closing several 5-year version gaps
and aligning with the net8.0 baseline. **If your application targets
net462, net472, or netstandard2.0**, your resolved
`Microsoft.Extensions.*` versions will increase (e.g., `Extensions.Http`
3.1.3 → 8.0.0, `Extensions.DependencyInjection` 2.1.0 → 8.0.0,
`Extensions.Caching.Memory` 2.1.0/6.0.2 → 8.0.1). Applications already
targeting net8.0+ are unaffected. See
[#​3787](AzureAD/microsoft-identity-web#3787).
- Bump `System.Text.Json` 8.0.5 → 8.0.6 (CVE-2024-43485). See
[#​3787](AzureAD/microsoft-identity-web#3787).
- Bump `Microsoft.AspNetCore.DataProtection` to 10.0.7 for CVE fix on
net10.0. See
[#​3796](AzureAD/microsoft-identity-web#3796).
- Bump `OpenTelemetry.Exporter.OpenTelemetryProtocol` 1.14.0 → 1.15.3.
See
[#​3788](AzureAD/microsoft-identity-web#3788).

**Full Changelog**:
AzureAD/microsoft-identity-web@4.8.0...4.9.0

Commits viewable in [compare
view](AzureAD/microsoft-identity-web@4.8.0...4.9.0).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Microsoft.Identity.Web.GraphServiceClientBeta&package-manager=nuget&previous-version=4.8.0&new-version=4.9.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: James Gunn <james@gunn.io>
Avery-Dunn added a commit that referenced this pull request May 6, 2026
…#3806)

Cherry-pick of PR #3793 from master to rel/3v with conflict resolution:
- Resolved merge conflicts in DownstreamApi.cs and DownstreamApi.Logger.cs
- Updated InternalAPI.Unshipped.txt for all target frameworks
- Adapted test method calls from UpdateRequestWithCertificateAsync to UpdateRequestAsync (3.x API)

Co-authored-by: Ignacio Inglese <iinglese@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants