Skip to content

Add Entra authentication to the Helix API client - #17366

Open
missymessa wants to merge 6 commits into
mainfrom
users/mjanecke/12269-helix-entra-client
Open

Add Entra authentication to the Helix API client#17366
missymessa wants to merge 6 commits into
mainfrom
users/mjanecke/12269-helix-entra-client

Conversation

@missymessa

Copy link
Copy Markdown
Member

Summary

  • use environment-specific Entra scopes for production and staging Helix API clients
  • send standard OAuth Bearer tokens through Azure.Core's expiry-aware authentication policy
  • preserve existing PAT overloads during the migration period
  • expose the selected authentication mode and scopes without logging credentials
  • support explicit scopes for custom Helix environments

Validation

  • targeted Microsoft.DotNet.Helix.Sdk.Tests build and test run
  • 0 warnings, 0 errors

Tracking: https://dev.azure.com/dnceng/internal/_workitems/edit/12269

Use environment-specific scopes and Azure.Core's expiry-aware Bearer policy for TokenCredential callers while preserving PAT overloads during migration. AB#12269

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e890b71a-c1aa-416c-a15c-be8da9fdd9b4
Copilot AI lite review requested due to automatic review settings August 18, 2026 20:55

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.

Pull request overview

Adds Entra ID (AAD) authentication support to the Helix C# API client by introducing scope-aware configuration in HelixApiOptions and new ApiFactory overloads, plus unit tests to validate mode/scope selection.

Changes:

  • Introduces HelixApiAuthenticationMode and exposes selected auth mode + token scopes via HelixApiOptions, selecting production/staging scopes by host and using BearerTokenAuthenticationPolicy for Entra credentials.
  • Adds ApiFactory.GetAuthenticated(...) overloads for TokenCredential (including an explicit-scope overload for custom hosts) while keeping PAT-based overloads.
  • Adds unit tests covering anonymous/PAT/Entra modes and default vs explicit scope behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/Microsoft.DotNet.Helix/Sdk.Tests/Microsoft.DotNet.Helix.Sdk.Tests/Microsoft.DotNet.Helix.Sdk.Tests.csproj Adds a direct project reference to the Helix client project to support new auth-option tests.
src/Microsoft.DotNet.Helix/Sdk.Tests/Microsoft.DotNet.Helix.Sdk.Tests/HelixApiAuthenticationTests.cs New tests validating auth mode selection and default/explicit scope behavior.
src/Microsoft.DotNet.Helix/Client/CSharp/HelixApiOptions.cs Implements Entra scope selection/exposure and configures expiry-aware bearer token auth policy.
src/Microsoft.DotNet.Helix/Client/CSharp/ApiFactory.cs Adds TokenCredential-based factory overloads for Entra authentication (including explicit-scope support).

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

Comment thread src/Microsoft.DotNet.Helix/Client/CSharp/ApiFactory.cs
Comment thread src/Microsoft.DotNet.Helix/Client/CSharp/ApiFactory.cs Outdated
Comment thread src/Microsoft.DotNet.Helix/Client/CSharp/HelixApiOptions.cs
@missymessa
missymessa requested review from chcosta and mmitche August 18, 2026 21:00
@missymessa

Copy link
Copy Markdown
Member Author

Reviewers added to this PR:

• Matt Mitchell ( mmitche ) — active owner and contributor across the Arcade Helix SDK/client.
• Christopher Costa ( chcosta ) — Helix submission/client SME with prior authentication and authorization review experience.

Use distinct Entra factory method names to preserve source compatibility and reject PAT credentials when explicit OAuth scopes are supplied.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e890b71a-c1aa-416c-a15c-be8da9fdd9b4
Copilot AI review requested due to automatic review settings August 18, 2026 21:02

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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/Microsoft.DotNet.Helix/Client/CSharp/HelixApiOptions.cs:37

  • The exception message says “Use the PAT-specific HelixApiOptions constructor instead”, but there is no PAT-specific HelixApiOptions overload (the PAT path is HelixApiOptions(Uri, TokenCredential) with a HelixApiTokenCredential, or ApiFactory.GetAuthenticated(...)). This could mislead callers; consider rewording the message to point at the actual constructor/API to use.
                throw new ArgumentException(
                    "Explicit scopes are only supported for Entra credentials. " +
                    "Use the PAT-specific HelixApiOptions constructor instead.",
                    nameof(credentials));

src/Microsoft.DotNet.Helix/Client/CSharp/HelixApiOptions.cs:87

  • GetDefaultScope accesses baseUri.Host without validating baseUri.IsAbsoluteUri. If a caller passes a relative Uri, this will throw an InvalidOperationException (“operation is not supported for a relative URI”) rather than a clear ArgumentException. Consider checking IsAbsoluteUri up front and throwing an ArgumentException with a helpful message/param name.
        private static string GetDefaultScope(Uri baseUri)
        {
            if (baseUri.Host.Equals("helix.dot.net", StringComparison.OrdinalIgnoreCase))
            {
                return ProductionScope;

Copilot AI review requested due to automatic review settings August 21, 2026 20:33

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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Suppressed comments (1)

src/Microsoft.DotNet.Helix/Client/CSharp/ApiFactory.cs:66

  • GetAuthenticatedWithEntra(string baseUri, TokenCredential credential) will silently return an anonymous client when credential is null (because HelixApiOptions(Uri, TokenCredential) permits null and InitializeOptions() selects Anonymous). Consider throwing ArgumentNullException when credential is null; same issue exists in the GetAuthenticatedWithEntra(TokenCredential credential) overload (ApiFactory.cs:28-31).
        /// <summary>
        /// Obtains an API client using an Entra credential for authenticated access to the provided Helix instance.
        /// Production and staging scopes are selected from the base URI.
        /// </summary>
        public static IHelixApi GetAuthenticatedWithEntra(string baseUri, TokenCredential credential)
        {
            return new HelixApi(new HelixApiOptions(new Uri(baseUri), credential));
        }

Comment thread src/Microsoft.DotNet.Helix/Client/CSharp/HelixApiOptions.cs
Comment thread src/Microsoft.DotNet.Helix/Client/CSharp/ApiFactory.cs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0e1a942f-a44f-4e3a-8d35-af3fe8bee535
Copilot AI review requested due to automatic review settings August 24, 2026 14:17

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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread src/Microsoft.DotNet.Helix/Client/CSharp/HelixApiOptions.cs
premun
premun previously approved these changes Aug 24, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0e1a942f-a44f-4e3a-8d35-af3fe8bee535
Copilot AI review requested due to automatic review settings August 24, 2026 16:54
@missymessa
missymessa enabled auto-merge (squash) August 24, 2026 16:58

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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Suppressed comments (1)

src/Microsoft.DotNet.Helix/Client/CSharp/ApiFactory.cs:75

  • GetAuthenticatedWithEntra(string baseUri, TokenCredential) accepts HelixApiTokenCredential (PAT) and will therefore create a PAT-authenticated client instead of Entra (HelixApiOptions treats HelixApiTokenCredential specially). To avoid silently selecting the wrong authentication mode, consider rejecting HelixApiTokenCredential here (ArgumentException) and directing callers to GetAuthenticated(baseUri, accessToken) instead. Same issue also exists in GetAuthenticatedWithEntra(TokenCredential) at ApiFactory.cs:35.
            return new HelixApi(new HelixApiOptions(new Uri(baseUri), credential));

Comment thread src/Microsoft.DotNet.Helix/Client/CSharp/ApiFactory.cs Outdated
Comment thread src/Microsoft.DotNet.Helix/Client/CSharp/HelixApiOptions.cs
Reject PAT credentials from the Entra factory methods, clarify direct HelixApiOptions guidance, and align the authentication test name with its assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9d86c2f6-8c72-4ce8-933a-841a368be1d9
Copilot AI review requested due to automatic review settings August 24, 2026 17:17
@missymessa
missymessa requested a review from premun August 24, 2026 17:18

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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@missymessa

Copy link
Copy Markdown
Member Author

@mmitche @chcosta @premun gentle ping

@missymessa

Copy link
Copy Markdown
Member Author

/azp run arcade-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

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