Skip to content

Sidecar: add per-route override gating and harden BaseUrl handling#3794

Merged
pmaytak merged 2 commits intomasterfrom
iinglese/sidecar-override-gating
Apr 30, 2026
Merged

Sidecar: add per-route override gating and harden BaseUrl handling#3794
pmaytak merged 2 commits intomasterfrom
iinglese/sidecar-override-gating

Conversation

@iNinja
Copy link
Copy Markdown
Contributor

@iNinja iNinja commented Apr 24, 2026

Description

Adds explicit, per-route control over whether optionsOverride.* query-string parameters are honoured by the sidecar's /AuthorizationHeader[/Unauthenticated] and /DownstreamApi[/Unauthenticated] endpoints, and unconditionally rejects optionsOverride.BaseUrl on every route.

Behaviour change

New configuration section Sidecar:AllowOverrides with four boolean flags:

Key Default
Sidecar:AllowOverrides:AuthorizationHeader true
Sidecar:AllowOverrides:AuthorizationHeaderUnauthenticated false
Sidecar:AllowOverrides:DownstreamApi true
Sidecar:AllowOverrides:DownstreamApiUnauthenticated false

When the flag for a route is false, any optionsOverride.* parameters on the request are dropped at bind time, the configured options are used as-is, and a single OverridesIgnored warning is logged with the route name. The request is still served — there is no 4xx.

optionsOverride.BaseUrl is rejected on every route regardless of the gating flag, with a BaseUrlOverrideIgnored warning. The OpenAPI document marks the optionsOverride.BaseUrl parameter as deprecated.

The unauthenticated routes default to false so that anonymous callers cannot influence outbound request shape; authenticated routes keep the existing permissive behaviour for backwards compatibility, but are now opt-out via configuration.

What's included

  • src/Microsoft.Identity.Web.Sidecar/Configuration/SidecarOptions.cs — new AllowOverrides nested options class with the four flags above.
  • src/Microsoft.Identity.Web.Sidecar/Models/BindableDownstreamApiOptions.csBindAsync now scans optionsOverride.* keys, drops BaseUrl early with a log, and only sets HasAny when a non-BaseUrl override is present (so a BaseUrl-only request produces a single warning, not two).
  • src/Microsoft.Identity.Web.Sidecar/Endpoints/AuthorizationHeaderEndpoint.cs, DownstreamApiEndpoint.cs — per-route lambdas inject IOptions<SidecarOptions> and pass allowOverrides plus a route-name string into the shared async handler.
  • src/Microsoft.Identity.Web.Sidecar/Logging/Logging.csOverridesIgnored(routeName) (EventId 3) and BaseUrlOverrideIgnored() (EventId 4).
  • src/Microsoft.Identity.Web.Sidecar/OpenAPI/Microsoft.Identity.Web.Sidecar.json — regenerated with the optionsOverride.BaseUrl parameter marked deprecated.
  • tests/E2E Tests/Sidecar.Tests/SidecarOverrideGatingTests.cs — 6 E2E tests covering each route × allow/deny combination.
  • tests/E2E Tests/Sidecar.Tests/ModelsTests.cs — 4 unit tests against BindAsync covering HasAny semantics (non-BaseUrl override, BaseUrl-only, mixed, none).
  • tests/E2E Tests/Sidecar.Tests/OptionsOverrideHeaderHandlingTests.cs — 2 cross-cutting tests, currently [Fact(Skip = "Pending dependency merge")]. These will be unskipped once PR 1 merges and master is merged back into this branch.

Notes for reviewers

  • No breaking change for existing deployments that only use the authenticated routes — defaults preserve current behaviour there.
  • Deployments that exposed /AuthorizationHeader/Unauthenticated or /DownstreamApi/Unauthenticated and relied on caller-supplied optionsOverride.* will need to opt back in by setting the corresponding flag to true.
  • The 2 skipped tests in OptionsOverrideHeaderHandlingTests.cs exercise the library-level header handling change from DownstreamApi: ignore caller-supplied reserved or duplicate headers in ExtraHeaderParameters #3793 through the sidecar surface; they pass locally on a branch that has both PRs applied. The skip is purely a sequencing convenience.

Adds an opt-in/opt-out configuration for whether 'optionsOverride.*'

query parameters are applied to a resolved DownstreamApiOptions on each

of the four sidecar routes:

  Sidecar:AllowOverrides:GetAuthorizationHeader              (default: true)

  Sidecar:AllowOverrides:GetAuthorizationHeaderUnauthenticated (default: false)

  Sidecar:AllowOverrides:CallDownstreamApi                   (default: true)

  Sidecar:AllowOverrides:CallDownstreamApiUnauthenticated     (default: false)

When the flag for a route is false, any 'optionsOverride.*' query

parameters are ignored and a single warning is logged.

'optionsOverride.BaseUrl' is now unconditionally ignored on every route

regardless of the flag, since the downstream BaseUrl is fixed by host

configuration. The OpenAPI document marks the parameter as deprecated.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@iNinja iNinja requested a review from a team as a code owner April 24, 2026 21:35
@pmaytak pmaytak merged commit e13b503 into master Apr 30, 2026
4 checks passed
@pmaytak pmaytak deleted the iinglese/sidecar-override-gating branch April 30, 2026 01:27
This was referenced May 1, 2026
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>
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