Skip to content

[BUG] Azure DevOps authentication via 'az login' does not always work #1671

@timjansenortec

Description

@timjansenortec

Describe the bug
When installing a custom agent, the installed md file is an html from ADO saying I am not logged in.

To Reproduce
logged in via 'az login'
using an apm.yml like this:

name: SomeApp
version: 1.0.0
description: SomeDescription
author: SomeAuthor
dependencies:
  apm:
  - https://dev.azure.com/SomeAzureDevOpsOrganization/SomeProject/_git/some-repo/agents/some-agent.agent.md
  mcp: []
includes: []
scripts: {}

then run:
set APM_DEBUG=1
apm update --verbose

output:

[DEBUG] Token setup: has_github_token=False, has_gitlab_token=False, has_ado_token=False, has_artifactory_token=False
[>] Resolving some-repo-backend-coding...
Resolved 1 direct dependencies (no transitive)
Phase: resolve -> 0.995s
[i] Update plan for apm.yml

  [+] SomeAzureDevOpsOrganization/SomeProject/some-repo/agents/some-agent.agent.md
      ref: - (-, new)

  1 added
  [+] added

Apply these changes? [y/N]: y
[i] No org policy found for dev.azure.com/SomeAzureDevOpsOrganization/.github
Phase: policy_gate -> 1.713s
[i] Targets: copilot  (source: auto-detect from .github/agents/, .github/copilot-instructions.md)
Phase: targets -> 0.018s
Phase: policy_target_check -> 0.000s
[DEBUG] Token setup: has_github_token=False, has_gitlab_token=False, has_ado_token=False, has_artifactory_token=False
[DEBUG] build_repo_url: host=dev.azure.com, kind=ado, dep_ref=present, ado_org=SomeAzureDevOpsOrganization
Preflight: dev.azure.com/SomeAzureDevOpsOrganization -- accepted
Phase: download -> 0.000s
  [+] dev.azure.com/SomeAzureDevOpsOrganization/SomeProject/some-repo/agents/some-agent.agent.md #main
    Auth: AAD_BEARER_AZ_CLI (unknown)
  |-- (files unchanged)
Phase: integrate -> 0.673s
Phase: cleanup -> 0.000s
Generated apm.lock.yaml with 1 dependencies
cache-pin: remote dep 'SomeAzureDevOpsOrganization/SomeProject/some-repo' has no resolved_commit; drift cannot verify its cache freshness. Re-run 'apm install' with
a pinned ref (commit, tag, or specific branch HEAD).
Phase: post_deps_local -> 0.000s
Phase: audit -> 0.012s
[#] Perf: 3 walks, 1 file matches, 6 files visited, 0.002s total walk time
[#] Perf:   apm_modules\SomeAzureDevOpsOrganization\SomeProject\some-repo-backend-coding: 3 walk(s) (2ms, 6 files visited, 1 matched)
[#] Perf: discovery: 4 call(s) (1 unique base(s), 3 cache hit(s), 75%)
Phase: finalize -> 0.000s
Updated 1 APM dependencies.

result:
File some-agent.agent.md will contain some html indicating that call was not authenticated:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html lang="en-US">
<head><title>
	
            Azure DevOps Services | Sign In
        
</title><meta http-equiv="X-UA-Compatible" content="IE=11;&#32;IE=10;&#32;IE=9;&#32;IE=8" />
    <link rel="SHORTCUT ICON" href="/favicon.ico"/>
...

Expected behavior
I expect that the correct md file is installed, or that I get an error that I need to login.

Environment (please complete the following information):

  • OS: Windows 10
  • Python 3.14.5
  • APM Version: 0.18.0

Additional context
If I try to install an individual skill, it does work. But it seems downloading goes through a different path.
The output contains lines like this:
Partial clone (--filter=blob:none) failed ...
[DEBUG] _clone_with_fallback: ...

I have tried adding some logging to the code to see what is happening.
It is not clear to me yet, but this is what I have seen with version 0.16.1:

  • in the resolve phase:
    apm gets into function 'download_ado_file' without fetching a bearer token via 'az'
    since there there are not credentials attached to the request, ado is giving back the html file which is then saved in apm_modules
    note that ado does not give a 401 for these situations
  • in the apply phase:
    apm does go through azure_cli.get_bearer_token, and succesfully gets a token
    the file is download again and saved again in apm_modules, still contains html, so apparently the bearer token is not attached?
    it seems the token is only used as a fallback, but somehow I don't get into that path.

Additionally I had to fix an error with 'az login' itself.
While trying to find out what was happening, I found out that 'az login' was giving an error like this
SubError: basic_action V2Error: invalid_grant AADSTS50078: Presented multi-factor authentication has expired due to policies configured by your administrator
APM did not report this in it's output (bug?)
Had to do this to fix it:
az logout
az login --tenant --scope "499b84ac-1321-427f-aa17-267ca6975798/.default"
After this fix, download the custom agent still failed.

Metadata

Metadata

Assignees

Labels

area/docs-sitedocs/src/content (Starlight), README, doc generation.area/enterpriseAir-gapped/GHE configurability, registry proxy, rulesets, adoption playbook.priority/highShips in current or next milestonestatus/acceptedDirection approved, safe to start work.status/shepherdingActively being driven by an APM shepherd runstatus/triagedInitial agentic triage complete; pending maintainer ratification (silence = approval).theme/securitySecure by default. Content scanning, lockfile integrity, MCP trust boundaries.type/bugSomething does not work as documented.

Type

No type
No fields configured for issues without a type.

Projects

Status
In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions