powershellauthenticationazure-devops-server-2020

Error running Invoke-RestMethod with $(System.AccessToken) in a build task


I'm getting a 401 (presumably) when attempting to access the REST API using the value of $(System.AccessToken) as a credential. The pipeline I'm running is on the same ADS 2020 on-prem server as the API URL I'm using.

The error message in the build logs goes like so:

TF400813: Resource not available for anonymous access. Client authentication required. - Azure DevOps Server

Inspired by this technique, here's the code from my PowerShell inline script task:

$Params = @{
  ContentType = 'application/json'
  Headers = @{ Authorization = 'Bearer $(System.AccessToken)' }
  Method = 'Get'
  Uri = 'http://host/collection/project/_apis/build/builds/' + $(Build.BuildId) + '?api-version=6.0'
}

$Result = Invoke-RestMethod @Params

I also tried this, borrowing from this answer:

$Params = @{
  ContentType = 'application/json'
  Method = 'Get'
  Uri = 'http://$(System.AccessToken)@host/collection/project/_apis/build/builds/' + $(Build.BuildId) + '?api-version=6.0'
}

$Result = Invoke-RestMethod @Params

I've taken care to turn on the Allow scripts to access the OAuth token option, as documented here.

The strange thing about it is that it worked the first time through (with the first code block above). Now, no matter what I try, I always get the above error.

How can I use the value of $(System.AccessToken) in a Build task to access the REST API on the same server?

--EDIT--

I've tried the alternate variable syntax as well:

$BuildId = $env:BUILD_BUILDID
$Token = $env:SYSTEM_ACCESSTOKEN

$Params = @{
  ContentType = 'application/json'
  Headers = @{ Authorization = 'Bearer $Token' }
  Method = 'Get'
  Uri = 'http://host/collection/project/_apis/build/builds/' + $BuildId + '?api-version=6.0'
}

$Result = Invoke-RestMethod @Params

Solution

  • After much angst, I finally found the combination that works:

    $BuildId = $env:BUILD_BUILDID
    $Token = $env:SYSTEM_ACCESSTOKEN
    
    $Params = @{
      ContentType = "application/json"
      Method = "Get"
      Uri = "http://host/collection/project/_apis/build/builds/$BuildId"
    }
    
    $Result = Invoke-RestMethod @Params -Headers @{ Authorization = "Bearer $Token" }
    

    I tried it on a whim. I have no idea why this passes when the others don't, but that's OK. It runs. I'm sticking a flag in it.