Skip to content

authentication: Use session issuers for enterprise routing - #8984

Merged
TylerLeonhardt merged 2 commits into
mainfrom
agents/authissuers-api-implementation
Sep 26, 2026
Merged

TylerLeonhardt merged 2 commits into
mainfrom
agents/authissuers-api-implementation

Conversation

@TylerLeonhardt

@TylerLeonhardt TylerLeonhardt commented Sep 26, 2026 •

Copy link
Copy Markdown
Member

Summary

Adopt the proposed authIssuers API from microsoft/vscode#337846 so GitHub Enterprise requests use the deployment identified by the selected authentication session, not github-enterprise.uri.

  • Derive REST/GraphQL endpoints from AuthenticationSession.authorizationServer, removing /login/oauth and preserving GHES/GHE.com mapping, deployment paths, and ports.
  • Keep issuer/token pairing through client reuse and scope upgrades; match repositories and host-specific caches to the selected deployment. Report missing enterprise provenance explicitly.
  • Preserve enterprise setup UI and public/PAT authentication. Enable authIssuers and require VS Code 1.140.0.

This is consumer adoption only: no multiple-host setting, provider, picker, or general authentication refactor. Production proposal allowlisting is handled separately in microsoft/vscode-distro; the API remains proposed.

Validation

  • Full desktop extension, browser extension, and webview compilation passed.
  • 141 focused mocked extension-host tests passed, including host B with host A configured, REST/GraphQL routing, public authentication, session changes, scope upgrades, and cache isolation.
  • npm run lint, npm run hygiene, and CRLF-aware diff checks passed.
  • Tests used isolated profiles and mocked authentication/network boundaries; no live authenticated network testing.

Unrelated local lockfile and API-declaration updates are excluded.

Fixes #8985

Adopt the proposed authIssuers API so enterprise clients, scope upgrades, and host caches follow the selected authentication session instead of github-enterprise.uri. Preserve enterprise setup UI and public authentication behavior.

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

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

🟡 Changes recommended

Repository instances can retain obsolete API clients after token refreshes or scope upgrades, alongside authentication fallback and telemetry issues.

Review effort: Balanced
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Adopts VS Code’s proposed authIssuers API to route enterprise operations using the selected authentication session’s deployment.

Changes:

  • Derives enterprise REST/GraphQL endpoints from session issuers.
  • Adds deployment-aware repository matching, caching, and session-change handling.
  • Updates API declarations, tests, minimum VS Code version, and release documentation.
File Description
package.json Enables authIssuers and raises VS Code requirement.
documentation/​releasing.md Documents the proposed API dependency.
src/​@types/​vscode.proposed.authIssuers.d.ts Declares issuer-related proposed APIs.
src/​authentication/​githubServer.ts Uses the authenticated deployment for discovery.
src/​common/​authentication.ts Derives deployment URIs from session issuers.
src/​common/​remote.ts Adds deployment-aware remote classification and matching.
src/​extension.ts Clears state when the enterprise server changes.
src/​gitExtensionIntegration.ts Isolates repository caches by API client.
src/​github/​copilotApi.ts Selects authenticated enterprise sessions directly.
src/​github/​credentials.ts Preserves issuer/token pairing and builds routed clients.
src/​github/​folderRepositoryManager.ts Matches remotes and cache paths to deployments.
src/​github/​githubRepository.ts Validates repository/session deployment affinity.
src/​github/​pullRequestOverview.ts Uses the repository’s authenticated server URI.
src/​github/​repositoriesManager.ts Updates enterprise authentication selection.
src/​issues/​util.ts Derives link origins from remotes.
src/​lm/​tools/​toolsUtils.ts Uses authenticated enterprise clients for tools.
src/​notifications/​notificationsProvider.ts Uses authenticated enterprise clients for notifications.
src/​test/​common/​remote.test.ts Tests deployment-aware remote matching.
src/​test/​github/​authIssuers.test.ts Covers issuer routing and session transitions.
src/​test/​github/​credentials.test.ts Updates credential test clients.
src/​test/​github/​folderRepositoryManager.test.ts Tests deployment-isolated caches.
src/​test/​issues/​issuesUtils.test.ts Tests remote-derived link origins.
src/​test/​mocks/​mockGitHubRepository.ts Adds server identity to mock clients.
src/​test/​view/​prsTree.test.ts Adds server identity to tree-test clients.

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

Comment thread src/github/githubRepository.ts
Comment thread src/github/repositoriesManager.ts Outdated
Comment thread src/github/credentials.ts
Refresh repository clients on session changes, honor enterprise login routing, and report unavailable authentication as failure. Add focused regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@TylerLeonhardt
TylerLeonhardt marked this pull request as ready for review September 26, 2026 02:27
Copilot AI review requested due to automatic review settings September 26, 2026 02:27
@TylerLeonhardt
TylerLeonhardt enabled auto-merge (squash) September 26, 2026 02:27

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

Deployment-path closing issue URLs are currently parsed with an incorrect repository owner.

Review effort: Balanced
Findings: None

Resolved since last review (3)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Include deployment path when parsing issue URLs

src/​github/​pullRequestOverview.ts:450

For an issuer such as https://host:8443/deployment/login/oauth, serverUri includes /deployment, but getIssueOrURLExpression only incorporates enterpriseUri.authority. A closing issue URL like /deployment/owner/repo/issues/12 is therefore parsed with owner deployment/owner, and URLs from another deployment on the same authority also match. Update the expression to include the escaped deployment path before the owner/repository capture, with coverage for both matching and mismatched deployment paths.

@TylerLeonhardt
TylerLeonhardt merged commit b642426 into main Sep 26, 2026
7 checks passed
@TylerLeonhardt
TylerLeonhardt deleted the agents/authissuers-api-implementation branch September 26, 2026 07:34
const issuer = session?.authorizationServer;
const oauthSuffix = '/login/oauth';
const path = issuer?.path.replace(/\/$/, '');
const unavailable = () => new AuthenticationError(vscode.l10n.t('GitHub Enterprise is unavailable because the authentication session does not include a supported authorization server. Use a VS Code build with authIssuers session support and sign in again.'));

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.

This shouldn't be possible, right? That's part of what the VS Code version bump prevents?

Comment thread src/github/credentials.ts
this._onDidUpgradeSession.fire();
}
return this.getHub(authProviderId);
return result.canceled || result.unavailable ? undefined : this.getHub(authProviderId);

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.

result.canceled || result.unavailable is also evaluated on line 502. To make it clearer what's being evaluated it would be good to put this into a const.

Comment thread src/github/credentials.ts
if (!hasScopesAlready) {
const session = this.getHub(authProviderId)?.session;
const result = await this.initialize(authProviderId, { createIfNone: !hasScopesAlready, ...(session ? sessionAccountOptions(session) : {}) }, SCOPES_WITH_ADDITIONAL, true);
if (!result.canceled && !result.unavailable && !hasScopesAlready && this.isAuthenticatedWithAdditionalScopes(authProviderId)) {

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.

We shouldn't need to check isAuthenticatedWithAdditionalScopes again here. We explicitly asked for the additional scopes on the previous line.

Comment thread src/github/credentials.ts
graphQLBaseUrl = `${enterpriseServerUri.scheme}://${enterpriseServerUri.authority}/api`;
}

const graphQLBaseUrl = enterpriseServerUri && !isGhe ? vscode.Uri.joinPath(enterpriseServerUri, 'api').toString() : baseUrl;

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.

Parens would make this line more readable.

public readonly onDidChangePullRequests: vscode.Event<PullRequestChangeEvent[]> = this._onDidChangePullRequests.event;

public get hub(): GitHub {
if (this._hub && this.remote.isEnterprise && (!this.authMatchesServer || !this.remote.matchesServerUri(this._hub.serverUri))) {

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.

How could this happen?

Comment on lines 311 to 328
@@ -317,11 +318,12 @@ export class RepositoriesManager extends Disposable {

let githubEnterprise;
const hasNonDotComRemote = (enterpriseRemotes.length > 0) || (unknownRemotes.length > 0);
if ((hasEnterpriseUri() || (dotComRemotes.length === 0)) && hasNonDotComRemote) {
const preferEnterprise = enterprise ?? (hasNonDotComRemote && (dotComRemotes.length === 0 || this._credentialStore.isAuthenticated(AuthProvider.githubEnterprise)));
if (preferEnterprise) {
githubEnterprise = await this._credentialStore.login(AuthProvider.githubEnterprise);
}
let github;
if (!githubEnterprise && (!hasEnterpriseUri() || enterpriseRemotes.length === 0)) {
if (!githubEnterprise && (!preferEnterprise || (enterprise !== true && enterpriseRemotes.length === 0))) {
github = await this._credentialStore.login(AuthProvider.github);
}

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.

Are these changes actually needed to suppor the issuer?

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.

Adopt the proposed authIssuers API for GitHub Enterprise

4 participants