Skip to content

Support configurable scheduler token audiences and government defaults - #806

Merged
Bernd Verst (berndverst) merged 3 commits into
mainfrom
configurable-token-audience
Sep 29, 2026
Merged

Bernd Verst (berndverst) merged 3 commits into
mainfrom
configurable-token-audience

Conversation

@berndverst

@berndverst Bernd Verst (berndverst) commented Sep 26, 2026 •

Copy link
Copy Markdown
Member

Summary

What changed?

  • Extend the existing DurableTaskSchedulerClientOptions.ResourceId and DurableTaskSchedulerWorkerOptions.ResourceId properties with shared normalization and per-options-instance defaults. No constructor or overload signatures change.
  • Support case-insensitive ResourceId connection-string configuration for all authentication types, including forwarding through named client/worker builders. Preserve already-normalized values when copying options so meaningful repeated /.default URI segments are not stripped twice.
  • Select https://durabletask.azure.us for missing/null/empty audiences when REGION_NAME starts with usgov or usdod, case-insensitively; retain https://durabletask.io otherwise. Explicit audiences always win.
  • Keep audience, service endpoint, and credential authority independent. Add optional AuthorityHost connection-string forwarding for SDK-created credentials that support it; omission preserves Azure Identity's defaults and environment configuration. Managed identity and developer-tool cloud configuration remain separate.
  • Verify actual requested scopes through recording credentials and loopback gRPC calls, including expiry/RefreshOn, cached concurrent calls, DI overloads, channel recreation, sandbox declaration/removal, registration reconnects, anonymous authentication, and supplied call invokers.
  • Update public XML documentation, the government-cloud README example, sandbox guidance, changelog, and package release notes. No package or dependency versions change.

Why is this change needed?

Applications need explicit/custom audiences and correct government-cloud defaults without silently changing endpoints or credential authority. Existing ResourceId options were not normalized or forwarded from connection strings.

Credential construction and authority-host rationale

The .NET SDK supports both caller-created credentials and SDK-created credentials. Credential construction from connection strings already existed before this PR; this PR does not introduce that ownership model.

Entry path Who constructs the credential? Authority responsibility
UseDurableTaskScheduler(endpointAddress, taskHubName, credential, ...) or setting options.Credential Caller Configure authority on the supplied credential. The SDK neither replaces it nor applies a per-request authority override.
UseDurableTaskScheduler(connectionString, ...) / DurableTaskSchedulerClientOptions.FromConnectionString(...) SDK, based on Authentication Optional AuthorityHost is passed into supported Azure Identity credential options before construction.
Worker connection-string equivalents SDK Same handling as the client.
UseSandboxWorker() SDK creates ManagedIdentityCredential Uses the hosting environment's identity endpoint; an Entra authority override does not apply.

Evidence at this PR's implementation commit:

Therefore the optional connection-string authority support is retained. No SDK authority property is added for caller-supplied credentials. Managed identity, Azure CLI, Azure PowerShell, and anonymous authentication do not receive this authority override; developer tools may need their own cloud configuration. Neither ResourceId nor REGION_NAME sets an authority or endpoint.

Issues / work items

Compatibility

This is not a breaking change to supported usage. Public-cloud deployments retain their existing default. Government/DoD deployments now select the audience registered in their cloud instead of the public-cloud audience. Calling a public-cloud scheduler from government cloud is not a supported scenario because the clouds are isolated; it is not an existing supported behavior that this PR must preserve. No migration is required for supported deployments.

Explicit audiences still take precedence regardless of REGION_NAME; this does not enable cross-cloud scheduler access. Explicit values are normalized, and whitespace-only or empty-after-normalization values produce actionable argument errors. The service endpoint and credential authority remain independently configured.

Existing property and constructor signatures remain intact; the setter's nullability annotation is widened. Orchestration replay, serialization, protobuf fields, and token-cache implementation are unchanged.


Project checklist

  • Release notes are not required for the next release
    • Otherwise: Notes added to CHANGELOG.md and both AzureManaged RELEASENOTES.md files
  • Backport is not required
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • All required tests have been added/updated (local unit and gRPC transport tests)
  • Breaking change?
    • If yes: N/A — supported deployments stay within their cloud; see compatibility rationale above.

AI-assisted code disclosure (required)

Was an AI tool used? (select one)

  • No
  • Yes, AI helped write parts of this PR (e.g., GitHub Copilot)
  • Yes, an AI agent generated most of this PR

If AI was used:

  • Tool(s): GitHub Copilot App.
  • AI-assisted areas/files: Implementation, regression tests, public documentation, release notes, and this description.
  • What you changed after AI output: Agent iterated on compilation, tests, documentation example compilation, government-environment regressions, and human review feedback. Compatibility wording incorporates the author's cloud-isolation clarification.

AI verification (agent verification completed; final human approval pending):

  • I understand the code and can explain it
  • I verified referenced APIs/types exist and are correct
  • I reviewed edge cases/failure paths (timeouts, retries, cancellation, exceptions)
  • I reviewed concurrency/async behavior
  • I checked for unintended breaking or behavior changes

Testing

Automated tests

  • 393 AzureManaged tests passed: client 181, worker 186, shared 26. All three suites also passed with REGION_NAME=UsGovVirginia (393 repeat executions).
  • Restored all nine default-audience assertions from the existing options/builder tests and expanded each to unset, public, mixed-case government, and mixed-case DoD regions. These tests save/restore REGION_NAME and use the existing nonparallel environment collection.
  • 19 existing channel-recreation regressions passed during initial implementation: client 10, worker 9.
  • Release builds of Client.AzureManaged and Worker.AzureManaged passed for net6.0, net8.0, and net10.0, with existing repository analyzer/obsolete-API warnings. Sandbox packages compile with the net10.0 test projects.
  • Targeted dotnet format style --no-restore --verify-no-changes checks passed for the changed source and tests; build-time .NET/StyleCop analyzers ran.
  • The whitespace formatter reports FINALNEWLINE: the existing .editorconfig requires insert_final_newline=false, while StyleCop requires a final newline. Existing final-newline conventions were retained rather than changing unrelated repository configuration. git diff --check passes with core.whitespace=cr-at-eol, preserving the changelog's existing CRLF format.
  • The government-cloud README example was compiled against the changed client and worker projects during initial implementation.
  • Confirmed that the existing GetReleaseNotes packaging target reads both AzureManaged RELEASENOTES.md files into PackageReleaseNotes; these files remain in use despite their stale historical entries.

Manual validation (only if runtime/behavior changed)

  • Environment: Windows, .NET SDK 10.0.401.
  • Actual scope arguments are recorded at TokenCredential.GetTokenAsync; loopback gRPC servers exercise the configured client/worker channels and sandbox management/registration transports.
  • No live public-cloud or Azure Government authentication was performed. Recording-credential scope verification and example compilation do not establish live cloud service availability or validate tenant/identity permissions.

Notes for reviewers

  • The common audience matrix is compiled into both client and worker test projects to keep authentication-path coverage identical without duplicating test logic.
  • Existing options/builder default assertions are retained with explicit environment inputs, alongside the comprehensive recording-credential matrix.
  • Sandbox transports already reuse scheduler channels; production sandbox changes are documentation only.
  • The token cache, refresh concurrency behavior, acquisition timing, and channel-recreation implementation were deliberately left unchanged.

Add ResourceId connection-string support and independent AuthorityHost forwarding. Preserve audience selection through DI, token refresh, and sandbox registration, with recording-credential regressions and government-cloud documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 26, 2026 07:03
Comment thread test/Worker/AzureManaged.Tests/SandboxAuthenticationTests.cs Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Copilot was unable to run its full agentic suite in this review.

Copilot review overview

Review effort: Lite
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

This PR updates Azure Managed client/worker configuration to treat ResourceId as a normalized token audience with region-based defaults (including a behavior change for gov/DoD regions) and adds optional AuthorityHost support for SDK-created Azure Identity credentials, with expanded shared authentication test coverage and documentation.

Changes:

  • Normalize ResourceId token audience handling with per-options-instance defaults, plus explicit-copy behavior for channel recreation/reconnect scenarios.
  • Add AuthorityHost parsing to connection strings and flow it into Azure Identity credential options where applicable.
  • Add shared and sandbox authentication tests, and document the new behavior (README, release notes, changelog).
File Description
test/​Worker/​AzureManaged.Tests/​Worker.AzureManaged.Tests.csproj Includes shared auth test code and defines SCHEDULER_WORKER to compile worker-specific shared tests.
test/​Worker/​AzureManaged.Tests/​SandboxAuthenticationTests.cs Adds worker sandbox registration/auth reconnect tests validating audience + token cache behavior.
test/​Worker/​AzureManaged.Tests/​DurableTaskSchedulerWorkerOptionsTests.cs Updates tests for new default ResourceId behavior (no longer fixed to durabletask.io).
test/​Worker/​AzureManaged.Tests/​DurableTaskSchedulerWorkerExtensionsTests.cs Updates extension tests for new default ResourceId behavior.
test/​Shared/​AzureManaged/​SchedulerAuthenticationTests.cs Adds shared authentication tests (client/worker via #if) and a local gRPC test server & credential recorder.
test/​Shared/​AzureManaged.Tests/​DurableTaskSchedulerConnectionStringTests.cs Adds tests for AuthorityHost preservation/validation in connection string credential option creation.
test/​Client/​AzureManaged.Tests/​SandboxAuthenticationTests.cs Adds client sandbox management/auth tests validating audience + token cache behavior.
test/​Client/​AzureManaged.Tests/​DurableTaskSchedulerClientOptionsTests.cs Updates tests for new default ResourceId behavior.
test/​Client/​AzureManaged.Tests/​DurableTaskSchedulerClientExtensionsTests.cs Updates extension tests for new default ResourceId behavior.
test/​Client/​AzureManaged.Tests/​Client.AzureManaged.Tests.csproj Includes shared auth test code for the client test project.
src/​Worker/​AzureManaged/​RELEASENOTES.md Documents ResourceId normalization/default behavior change and AuthorityHost support.
src/​Worker/​AzureManaged/​DurableTaskSchedulerWorkerOptions.cs Implements per-instance default ResourceId, normalization, AuthorityHost credential options forwarding, and copy semantics.
src/​Worker/​AzureManaged/​DurableTaskSchedulerWorkerExtensions.cs Ensures ResourceId is copied from connection options when configuring via extensions.
src/​Worker/​AzureManaged.Sandboxes/​DurableTaskSchedulerSandboxWorkerExtensions.cs Documents shared audience behavior for worker + sandbox registration.
src/​Shared/​AzureManaged/​DurableTaskSchedulerResourceId.cs Adds shared default resolution + normalization for token audience URIs.
src/​Shared/​AzureManaged/​DurableTaskSchedulerConnectionString.cs Adds connection-string ResourceId property and AuthorityHost-aware credential options creation.
src/​Client/​AzureManaged/​RELEASENOTES.md Documents ResourceId normalization/default behavior change and AuthorityHost support.
src/​Client/​AzureManaged/​DurableTaskSchedulerClientOptions.cs Mirrors worker changes for client options (per-instance default, normalization, copy semantics, authority host forwarding).
src/​Client/​AzureManaged/​DurableTaskSchedulerClientExtensions.cs Ensures ResourceId is copied from connection options when configuring via extensions.
src/​Client/​AzureManaged.Sandboxes/​SandboxActivitiesClientServiceCollectionExtensions.cs Documents that sandbox management reuses the configured client channel/audience.
samples/​on-demand-sandbox/​README.md Adds guidance for gov cloud audience + authority configuration.
README.md Adds comprehensive documentation on token audiences, gov defaults, normalization, and AuthorityHost.
CHANGELOG.md Captures behavior change and new connection-string support.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread test/Shared/AzureManaged/SchedulerAuthenticationTests.cs
@berndverst

Copy link
Copy Markdown
Member Author

Visual overview: configurable token audiences

PR 806 logic: an explicit ResourceId wins; otherwise usgov/usdod region prefixes select the government audience and other regions select the public audience. Normalize explicit input once, append /.default, and retain the audience across refreshes and reconnects. ResourceId, credential authority, and service endpoint remain independent.

Purpose: support custom and government-cloud token audiences consistently across clients, workers, and sandbox management/registration without changing the service endpoint or credential authority implicitly.

  • Precedence: explicit nonempty ResourceId overrides the region. Otherwise, case-insensitive usgov/usdod prefixes select https://durabletask.azure.us; everything else selects https://durabletask.io.
  • Normalization: trim surrounding whitespace and trailing /, remove one case-insensitive /.default suffix, trim trailing / again, then request <audience>/.default. Explicit values that normalize to empty are rejected, not defaulted.
  • Authority ownership: callers configure their supplied credentials. Connection-string paths construct credentials in the SDK and accept optional AuthorityHost for supported credential types. Omission preserves Azure Identity defaults; managed identity and developer-tool cloud settings remain separate.
  • Migration: explicitly set ResourceId=https://durabletask.io to preserve the former public audience in government/DoD regions.

Illustration generated with Microsoft Copilot and reviewed against this PR. Scope behavior was verified with recording credentials and local gRPC servers, not live cloud authentication.

Use atomic token issuance to select the first expiring or refreshable token, cover concurrent requests, and explain the sandbox registration stream drain.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 28, 2026 17:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The changes span authentication, regional defaults, credential authority, sandbox paths, and reconnect behavior, warranting final human review.

Review effort: Lite
Findings: None

Resolved since last review (2)

@berndverst

Copy link
Copy Markdown
Member Author

@microsoft-github-policy-service rerun

@halspang halspang left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments, mostly I'm concerned about the potential behavioral change. Behavioral changes tend to mean breaking changes.

It seems to me, like the breaking change here, would be that a user who hasn't explicitly set this but has their workers in a usgov region but pointing at a public scheduler would break? This seems unlikely but it's not impossible. However, is this a supported case in the gov regions? Can they call out to standard prod resources?

Comment thread CHANGELOG.md Outdated
Comment thread src/Client/AzureManaged/RELEASENOTES.md Outdated
Comment thread src/Shared/AzureManaged/DurableTaskSchedulerResourceId.cs Outdated
Comment thread src/Worker/AzureManaged/RELEASENOTES.md Outdated
@berndverst

Copy link
Copy Markdown
Member Author

A few comments, mostly I'm concerned about the potential behavioral change. Behavioral changes tend to mean breaking changes.

It seems to me, like the breaking change here, would be that a user who hasn't explicitly set this but has their workers in a usgov region but pointing at a public scheduler would break? This seems unlikely but it's not impossible. However, is this a supported case in the gov regions? Can they call out to standard prod resources?

That is not a breaking change because it is simply unsupported invalid behavior. Clouds are intended to be siloed. Using a DTS scheduler homed in public cloud from Government Cloud for example would make it impossible to use any auth except hardcoded client key / secret (or cert) taken from public cloud but somehow injected into the Government cloud instance.

In Government cloud it is the expectation that all Azure services use login.microsoftonline.us and the service principals for Microsoft owned apps available to Government cloud. The durabletask.io audience does not resolve a service principle in Government cloud when using login.microsoftonline.us because that is not a valid app registration in this siloed cloud.

Restore all default-audience assertions with isolated public, government, and DoD cases. Align the changelog and compatibility documentation with supported same-cloud deployments and move the scope suffix constant to class scope.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 29, 2026 00:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The broad authentication and cloud-configuration changes require final human review.

Review effort: Lite
Findings: None

@berndverst
Bernd Verst (berndverst) merged commit d0191fa into main Sep 29, 2026
11 checks passed
@berndverst
Bernd Verst (berndverst) deleted the configurable-token-audience branch September 29, 2026 01:20
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.

3 participants