{Profile} az login: Support automatic OIDC federated token refresh - #33989
Draft
MaddyMicrosoft wants to merge 5 commits into
Draft
{Profile} az login: Support automatic OIDC federated token refresh#33989MaddyMicrosoft wants to merge 5 commits into
MaddyMicrosoft wants to merge 5 commits into
Conversation
… federated tokens Static `--federated-token` values expire in ~10 minutes and cannot be refreshed, so long-running CI/CD tasks fail with `AADSTS700024: Client assertion is not within its valid time range`. This registers a callable client_assertion with MSAL (the documented, recommended interface) so an expired OIDC ID token is transparently re-fetched on every token acquisition, including in later `az` processes. Wiring: - New `FEDERATED_IDENTITY` sentinel persisted as the SP entry's client_assertion. - `ServicePrincipalAuth.get_msal_client_credential()` resolves that sentinel to a provider dispatcher, `get_federated_id_token()`, instead of a static string. - Dispatcher implements GitHub Actions; other environments raise a clear error pointing at `--federated-token`. Azure DevOps is a planned follow-up (Azure#28708). - New `az login --federated-identity` flag, mutually exclusive with `--federated-token` and only valid with `--service-principal`. Adds unit tests covering the sentinel-to-callable resolution, the GitHub fetch (success and HTTP error), and the unsupported/no-provider branches. Partially addresses Azure#28708 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…token refresh Extends `--federated-identity` (GitHub Actions only) to also refresh OIDC federated tokens on Azure DevOps Pipelines, so long-running pipeline tasks no longer fail with `AADSTS700024`. The provider dispatcher now detects Azure DevOps and POSTs to the pipeline oidctoken API, following the documented Azure DevOps / azure-identity `AzurePipelinesCredential` contract. Because the refresh runs in a later `az` process, the three required inputs are read from the environment: - request URL: ARM_OIDC_REQUEST_URL, else SYSTEM_OIDCREQUESTURI - access token: ARM_OIDC_REQUEST_TOKEN, else SYSTEM_ACCESSTOKEN (System.AccessToken) - service conn: ARM_OIDC_AZURE_SERVICE_CONNECTION_ID Missing variables produce a clear, actionable error. Adds unit tests for the Azure DevOps success path, missing-environment handling, and updates the help text. Partially addresses Azure#28708 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…oken refresh Adds a provider-agnostic escape hatch alongside the built-in `--federated-identity` providers. `--federated-token-callback <command>` takes any command that prints a fresh OIDC token to stdout; Azure CLI wraps it as the MSAL client_assertion callable and re-runs it on demand, so token refresh works with any CI/CD system (not just the built-in GitHub Actions / Azure DevOps providers) without platform-specific logic in the CLI. - The command is persisted (client_assertion_callback) so later `az` processes rebuild the callable and refresh independently. - Mutually exclusive with --federated-token and --federated-identity; service principal only. Clear errors on non-zero exit or empty output. The token value is never logged. The three flags now cover the full spectrum: static token (--federated-token), built-in providers (--federated-identity), and universal callback (--federated-token-callback). Partially addresses Azure#28708 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends Azure CLI service-principal login to support automatically refreshing OIDC federated tokens, avoiding long-running job failures due to expired assertions. It does so by introducing a provider-detected refresh mode (--federated-identity) and a generic “run a command to fetch a fresh token” mode (--federated-token-callback) that can be persisted and re-used by later az processes.
Changes:
- Adds
--federated-identityand--federated-token-callbackarguments toaz loginand wires them into SP credential construction. - Introduces a persisted sentinel (
FEDERATED_IDENTITY) and refresh callbacks inServicePrincipalAuth.get_msal_client_credential(). - Adds unit tests covering sentinel persistence, callback wrapping, and CI-provider token retrieval.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/azure-cli/azure/cli/command_modules/profile/custom.py | Adds new az login parameters and validation; passes new federated options into SP credential creation. |
| src/azure-cli/azure/cli/command_modules/profile/init.py | Exposes new CLI arguments (--federated-identity, --federated-token-callback) and help text. |
| src/azure-cli-core/azure/cli/core/auth/identity.py | Implements provider-detected token refresh, a persisted sentinel, and a command-based assertion callback path. |
| src/azure-cli-core/azure/cli/core/auth/tests/test_identity.py | Adds unit tests for federated identity sentinel behavior, callback behavior, and provider detection flows. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
MaddyMicrosoft
marked this pull request as draft
August 26, 2026 01:55
- Harden --federated-token-callback: parse the command into an argv list and run it without a shell (shell=False), so a tampered token cache cannot become arbitrary code execution. Users needing pipes/redirection use a script or wrap in bash -c. - Reject combining --federated-token/--federated-identity/--federated-token-callback with --password or --certificate (previously the secret silently won and refresh was silently disabled). - Fix the GitHub OIDC request URL to append the audience with the correct separator when the URL has no existing query string. - Correct the misleading --service-principal usage error to list all credential modes. - Align --federated-identity help text with the actual mutual-exclusion validation. - Add tests for the no-shell argv behavior and the query-less GitHub URL case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…on-length linter The --federated-token-callback option (26 chars) exceeds azure-cli's 22-char option-length threshold, so add the shorter --federated-token-cmd alias. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Collaborator
|
Feature/OIDC token refresh |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 PR Validation —⚠️ Review suggested
Related command
az loginDescription
Service-principal login with an OIDC federated token currently accepts only a static
token via
--federated-token. That token expires in ~5–10 minutes and cannot be refreshed,so long-running CI/CD tasks fail with
AADSTS700024: Client assertion is not within its valid time rangeThis adds automatic, on-demand refresh by registering a callable
client_assertionwithMSAL (the documented, recommended interface). When the access token expires and a new one is
needed, MSAL invokes the callback to fetch a fresh ID token — including in later
azprocesses.Three ways to supply the assertion (mutually exclusive with each other and with
--password/--certificate):--federated-token <token>— static token (existing behavior, unchanged).--federated-identity— auto-detects the CI/CD provider and refreshes the token itself.Supports GitHub Actions and Azure DevOps.
--federated-token-callback <command>(alias--federated-token-cmd) — provider-agnostic:runs a user-supplied command that prints a fresh token to stdout. Runs without a shell for safety.
Testing Guide
test_identity.pycover sentinel→callable resolution, GitHub and Azure DevOpstoken fetch (success + error paths), the no-shell callback behavior, and usage validation.
az login --service-principal -u <id> -t <tenant> --federated-identityin aGitHub Actions (with
id-token: write) or Azure DevOps (withSystem.AccessTokenmapped)job and confirm a >10-minute task no longer fails with AADSTS700024.
History Notes
[Component Name 1] BREAKING CHANGE:
az command a: Make some customer-facing breaking change[Component Name 2]
az command b: Add some customer-facing featureThis checklist is used to make sure that common guidelines for a pull request are followed.
The PR title and description has followed the guideline in Submitting Pull Requests.
I adhere to the Command Guidelines.
I adhere to the Error Handling Guidelines.