Skip to content

feat(azure): support Entra ID bearer token auth via AZURE_OPENAI_AD_TOKEN#9716

Merged
DOsinga merged 4 commits into
aaif-goose:mainfrom
hammadxcm:fix/azure-ad-token-auth
Jun 17, 2026
Merged

feat(azure): support Entra ID bearer token auth via AZURE_OPENAI_AD_TOKEN#9716
DOsinga merged 4 commits into
aaif-goose:mainfrom
hammadxcm:fix/azure-ad-token-auth

Conversation

@hammadxcm

Copy link
Copy Markdown
Contributor

Summary

Fixes #9548

In enterprise deployments (e.g. hosted VS Code / code-server), only a short-lived Azure OpenAI access token is exposed to the runtime, while Azure credentials (client ID, secret, tenant) stay in a backend service. The Azure OpenAI provider previously supported only API keys or acquiring its own token through the Azure CLI credential chain, so this deployment pattern wasn't possible.

Changes

  • Add a BearerToken variant to AzureCredentials, populated from a new optional secret config key AZURE_OPENAI_AD_TOKEN (works from env var or config.yaml, same as the API key).
  • When set, the token is sent directly as Authorization: Bearer <token> and Azure CLI / token acquisition is skipped entirely — no caching, no subprocess.
  • Precedence: AZURE_OPENAI_AD_TOKEN > AZURE_OPENAI_API_KEY > Azure credential chain (the AD token is short-lived and explicitly injected, so setting it signals intent). Documented in the provider docs.
  • Registered the key in provider metadata (optional, secret) and the curated catalog so the Desktop setup UI shows it as a masked optional field.
  • Updated documentation/docs/getting-started/providers.md (provider table + the Azure OpenAI auth section, now listing all three methods and their precedence).

Behavior is unchanged when the new variable is unset (empty values are filtered, matching the AWS_BEARER_TOKEN_BEDROCK pattern).

Testing

  • New unit tests in azureauth.rs: credential selection precedence (token > key > default chain) and get_token() returning the bearer token without invoking the Azure CLI.
  • New unit tests in azure.rs: auth header is Authorization: Bearer <token> for the bearer path and api-key for the API key path.
  • cargo fmt, cargo clippy --all-targets -- -D warnings (with aws-providers), and cargo test -p goose providers::azure (7/7 passing) all clean.

Manual verification of the token flow matches the issue author's setup: a token from az account get-access-token --resource https://cognitiveservices.azure.com placed in AZURE_OPENAI_AD_TOKEN authenticates directly.

…OKEN

In enterprise deployments only a short-lived Azure OpenAI access token
is exposed to the runtime, while Azure credentials stay in a backend
service. The Azure OpenAI provider previously supported only API keys
or acquiring its own token through the Azure CLI credential chain.

Add a BearerToken credential variant populated from the optional
AZURE_OPENAI_AD_TOKEN config key. When set, the token is sent directly
as 'Authorization: Bearer <token>' and Azure CLI / token acquisition is
skipped. Precedence: AD token > API key > credential chain.

Fixes aaif-goose#9548

Signed-off-by: hammadxcm <hammadkhanxcm@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a486e10ceb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


1. **API Key Authentication** - Uses the `AZURE_OPENAI_API_KEY` for direct authentication
2. **Azure Credential Chain** - Uses Azure CLI credentials automatically without requiring an API key
1. **Entra ID Bearer Token** - Uses a pre-acquired Microsoft Entra access token from `AZURE_OPENAI_AD_TOKEN`, sent as `Authorization: Bearer <token>`. goose skips Azure CLI and token acquisition entirely, which suits enterprise deployments where only short-lived tokens are exposed to the runtime (e.g. obtained via `az account get-access-token --resource https://cognitiveservices.azure.com`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Extract only the accessToken value in the example

When users populate the variable through command substitution from this example, az account get-access-token defaults to JSON containing accessToken, expiry, tenant, and other fields, so goose sends that entire JSON document as the bearer credential and authentication fails. The Azure CLI documentation confirms that the default output is JSON and supports --query and TSV output; show an extraction such as --query accessToken --output tsv so the documented command produces the value expected by AZURE_OPENAI_AD_TOKEN.

Useful? React with 👍 / 👎.

The az CLI outputs a JSON document by default, so command substitution
from the previous example would set AZURE_OPENAI_AD_TOKEN to the whole
JSON instead of the token value.

Signed-off-by: hammadxcm <hammadkhanxcm@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ba193b5a7e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/goose/src/providers/azure.rs Outdated
ConfigKey::new("AZURE_OPENAI_DEPLOYMENT_NAME", true, false, None, true),
ConfigKey::new("AZURE_OPENAI_API_VERSION", false, false, None, false),
ConfigKey::new("AZURE_OPENAI_API_KEY", false, true, Some(""), true),
ConfigKey::new("AZURE_OPENAI_AD_TOKEN", false, true, Some(""), false),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Expose the Entra token in the setup catalog

Marking this key non-primary prevents it from appearing in ACP/native configuration flows: setup_entry_from_metadata in crates/goose-providers/src/canonical/catalog.rs builds fields using only keys where key.primary is true. Consequently those clients cannot enter the new token at all, and the newly added AZURE_OPENAI_AD_TOKEN field override is unreachable there. Make the token primary or extend the setup catalog to expose alternative/advanced authentication fields.

Useful? React with 👍 / 👎.

hammadxcm and others added 2 commits June 10, 2026 18:21
The setup catalog and ACP/native configuration flows only surface
config keys with primary set, so the field (and its curated label)
was unreachable in those clients. The key remains optional and
secret, so it renders as an optional masked field.

Signed-off-by: hammadxcm <hammadkhanxcm@gmail.com>
Signed-off-by: Douwe M Osinga <douwe@sidewalklabs.com>

@DOsinga DOsinga left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the contribution! This cleanly adds Entra ID bearer token auth via AZURE_OPENAI_AD_TOKEN, follows the existing credential pattern, has meaningful tests, and addresses both codex comments. I pushed a small follow-up renaming the docs section heading to cover all three auth methods. LGTM.

@DOsinga DOsinga added this pull request to the merge queue Jun 17, 2026
Merged via the queue into aaif-goose:main with commit b3d3a8b Jun 17, 2026
23 checks passed
lifeizhou-ap added a commit that referenced this pull request Jun 17, 2026
* main: (66 commits)
  feat: implement acp method for elicitation and elicitation improvement (#9797)
  fix: removed window goosed when closing window (#9818)
  View json (#9678)
  Make the context exceeded checker more precise (#9831)
  feat: load global hints from ~/.agents/AGENTS.md (#9736)
  fix: inherit login-shell PATH in spawned subagents (#9737)
  feat(gym): make per-agent timeout configurable (GYM_AGENT_TIMEOUT) (#9791)
  fix: accept string values for GOOSE_CONTEXT_LIMIT (#9738)
  feat(azure): support Entra ID bearer token auth via AZURE_OPENAI_AD_TOKEN (#9716)
  fix: clear rejected OAuth credentials after refresh (#9694)
  use windows-2022 image for CUDA builds (#9834)
  fix: keep extended thinking within the Anthropic output cap (#9814)
  fix(packaging): disable RPM build-id links (#9671)
  fix(providers/openai): preserve custom API path in base_url derivation (#9649)
  feat(i18n): language selection feature (#9405)
  fix(desktop): handle resume deep links (#9298)
  feat: added _meta.conversationBefore for ACP forking session (#9821)
  chore(deps): bump shlex from 1.3.0 to 2.0.1 (#9505)
  chore(deps): bump actions/deploy-pages from 4.0.5 to 5.0.0 (#9499)
  chore(deps): bump actions/upload-pages-artifact from 4.0.0 to 5.0.0 (#9497)
  ...
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.

Support Azure OpenAI Bearer Token Authentication (AZURE_OPENAI_AD_TOKEN)

2 participants