Search code examples
azurepowershellazure-devopsmicrosoft-entra-id

How to query Azure DevOps Work Items using client_id and client_secret


I want to query Work Items through the Azure DevOps REST API. This is working when I'm using my PAT with work_write access.

Now I want to to the same using an application that should to this.

The steps I did:

  1. Create a new application in Microsoft Entra through the Azure portal
  2. Gave vso.work_write permission to that application and granted admin consent (although admin consent should not be needed)
  3. Created a client_secret
  4. Added that application as a user in Azure Devops and added assigned it the "Project Contributor" role to the project that I want to query.

I'm using the below PowerShell code to sign in and query the Work Items. I can successfully sign in and I'm getting an access_token that looks just fine. However the response to the WIQL query is the HTML of the sign in page. I tested the same query using a PAT I created from my account using the same work_write permission and it worked just fine.

# Define the variables
$organization = "..."
$project = "..."
$clientId = "..."
$tenantId = "..."
$clientSecret = "..."
$baseurl = "https://dev.azure.com/$organization/$project"
$tokenurl = "https://login.microsoftonline.com/$tenantId/oauth2/token"

# Get the access token
$body = @{
    client_id = $clientId
    client_secret = $clientSecret
    grant_type = "client_credentials"
    scope = "https://app.vssps.visualstudio.com/vso.work_write"
}
$tokenresponse = Invoke-RestMethod -Uri $tokenurl -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
$token = $tokenresponse.access_token
echo $tokenresponse # This looks fine

# Define the WIQL query
$wiql = @{
    query = "SELECT [System.Id], [System.AssignedTo], [System.State], [System.Title] FROM workitems WHERE [System.TeamProject] = '$project' AND [System.State] = 'Resolved' AND [System.ChangedDate] < @today-7 AND [System.Tags] NOT CONTAINS 'Stale'"
} | ConvertTo-Json

# Post the WIQL query to the REST API
$wiqlurl = "$baseurl/_apis/wit/wiql?api-version=7.1"
$wiqlresponse = Invoke-RestMethod -Uri $wiqlurl -Method Post -Body $wiql -ContentType "application/json" -Headers @{Authorization=("Bearer {0}" -f $token)}

echo $wiqlresponse # This is the html of the sign in page

What do I need to change in order to successfully execute the query?


Solution

  • To resolve the error, you need to change scope value to 499b84ac-1321-427f-aa17-267ca6975798/.default and use v2.0 token URL in your PowerShell script.

    In my case, I registered one Azure AD application and added it as user in Azure DevOps- organization with "Project Contributor" role:

    enter image description here

    Now, I ran below modified script by changing values of $scope and $tokenurl parameters like this:

    # Define the variables
    $organization = "sridevOpsdemo"
    $project = "sriproj1"
    $clientId = "appId"
    $tenantId = "tenantId"
    $clientSecret = "secret"
    $baseurl = "https://dev.azure.com/$organization/$project"
    $tokenurl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
    
    # Get the access token
    $body = @{
        client_id = $clientId
        client_secret = $clientSecret
        grant_type = "client_credentials"
        scope = "499b84ac-1321-427f-aa17-267ca6975798/.default"
    }
    $tokenresponse = Invoke-RestMethod -Uri $tokenurl -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
    $token = $tokenresponse.access_token
    echo $tokenresponse
    
    $wiql = @{
        query = "Select [System.Id], [System.Title], [System.State] From WorkItems Where [System.WorkItemType] = 'Task' order by [Microsoft.VSTS.Common.Priority] asc, [System.CreatedDate] desc"
    } | ConvertTo-Json
    
    $wiqlurl = "$baseurl/_apis/wit/wiql?api-version=7.1"
    $wiqlresponse = Invoke-RestMethod -Uri $wiqlurl -Method Post -Body $wiql -ContentType "application/json" -Headers @{Authorization=("Bearer {0}" -f $token)}
    

    Response:

    enter image description here

    When I echoed $wiqlresponse, I got response with work items details successfully like below:

     echo $wiqlresponse
    

    enter image description here

    Reference:

    Use service principals & managed identities - Azure DevOps | Microsoft