Skip to content

Azure cli auth - #43037

Closed
neriousy wants to merge 36 commits into
devfrom
azure-cli-auth
Closed

neriousy wants to merge 36 commits into
devfrom
azure-cli-auth

Conversation

@neriousy

@neriousy neriousy commented Aug 17, 2026 •

Copy link
Copy Markdown
Member

Issue for this PR

N/A

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds Microsoft Entra ID through the Azure CLI as a login method for the existing Azure provider. OpenCode uses the active az login session to find the resource group and deployed models, keeps only successful deployments that exactly match the Azure models.dev catalog, and preserves each deployment name for inference.

Requests use cached Azure CLI tokens with the correct audience for Azure OpenAI/model inference and Foundry-native endpoints. The existing API-key flow is unchanged, and discovery failures make Azure unavailable without blocking startup.

How did you verify your code works?

  • bun test test/provider/provider.test.ts test/plugin/azure.test.ts (106 passing)
  • bun typecheck
  • bun dev models azure discovered both GPT-5 Mini and DeepSeek V4 Flash from the active Azure subscription

Screenshots / recordings

Azure CLI login flow

If this is a UI change, please include a screenshot or recording.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

If you do not follow this template your PR will be automatically rejected.

OpeOginni and others added 26 commits June 8, 2026 13:23
@neriousy
neriousy marked this pull request as ready for review August 17, 2026 12:50
@neriousy neriousy self-assigned this Aug 17, 2026
@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference; please use your judgment.

  1. packages/opencode/src/plugin/azure.ts:31 — expires_on is typed Schema.Number, but az account get-access-token --output json has returned expires_on as a string of unix seconds on several Azure CLI versions (and expiresOn as a locale datetime string); on those installs every decode fails and the whole OAuth path breaks at first use — accept both shapes (Schema.Union([Schema.Number, Schema.NumberFromString]) or explicit coercion) and add a fixture test using the string form.

  2. packages/opencode/src/plugin/azure.ts:52 — the token cache has no single-flight: after expiry, N concurrent requests launch N parallel az account get-access-token child processes (~hundreds of ms each) before any result lands in the Map — memoize the in-flight promise per scope (tokens.set(scope, pending) pattern) so concurrent misses share one CLI call.

  3. packages/opencode/src/plugin/azure.ts:88 — .catch(() => ({})) makes CLI/discovery failures completely invisible: a user with the wrong subscription sees an empty model list with zero diagnostics — log at debug/warning (resource name + error class) so support can tell "no deployments" apart from "az not logged in".

  4. packages/opencode/src/plugin/azure.ts:63 — headers.delete("api-key")/x-api-key then unconditional Bearer overwrite is right for defense-in-depth, but note it also strips any user-configured static api-key header a custom model entry might have intentionally supplied for hybrid setups — probably intended (Entra-only enforcement), just document it in providers.mdx next to the new section.

  5. Nit — packages/opencode/src/plugin/azure.ts:150 — scopeForRequest sends anything that isn't Foundry to the Cognitive Services scope, including non-Azure hosts; harmless while this fetch is bound to azure-provider routes only, but a comment stating that assumption would prevent misuse if the loader ever gets reused for other base URLs.

Overall: well-built feature — clean separation of createAzureAuthHooks(shell, request) makes the 259-line test suite possible, scope selection matches Microsoft's documented split, and the resourceName fallback chain (provider options → api metadata → oauth accountId → env) closes a real gap in provider.ts. Item 1 is the ship-blocker to verify; 2–3 are quick wins. Thanks!

@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference; please use your judgment.

  • packages/opencode/src/plugin/azure.ts:118 (discoverAzureModels) — .catch(() => ({})) silently swallows every discovery failure, including RBAC denials and az not being installed. The user just sees an empty model list with no explanation; consider logging a warning (or surfacing the error message in the UI) so misconfiguration is diagnosable.
  • packages/opencode/src/plugin/azure.ts:33 (token) — cache is keyed by scope only; if the user runs az account set --subscription other mid-session, requests keep using the old tenant's token until it lapses near the 60s refresh buffer. Probably rare, worth a comment or cache invalidation hook.
  • The dummy 365-day expires on the stored oauth entry is clever (real freshness lives in the CLI), but it also means the client will never prompt for re-auth when az login itself has lapsed — the docs do call this out ("sign in again when the CLI session expires"), good.
  • Scope routing in scopeForRequest (foundry vs cognitiveservices by hostname/path) is well-tested, including header stripping of api-key/x-api-key while preserving unrelated headers.
  • Test suite is excellent — mocked shell/fetch seams, negative cases (discovery failure keeps startup alive), and exact az command assertions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants