Adding Azure AD Groups to Azure Devops Projects Groups using Rest API fails

Nathanael Santschi 136 Reputation points
2022-11-23T15:00:41.327+00:00

We've created a script which should do the following using die Azure DevOps Rest API and Mgraph:

  • Create Azure DevOps Project - using a PAT which has full access
  • Create Azure AD Groups based on Projectname for Contributors and Project Admins - over mgraph using app registration with api group write read permissions
  • Add those Azure AD Groups as member to the relating Azure DevOps Group Permissions

What doesn't work using the REST API with a PAT is adding the Azure AD Groups as member to the Project Group Permission.

We are getting the following error:
WARNING: The remote server returned an error: (401) Unauthorized.

But we can't see which permissions are missing - the PAT has full access to everything and the app registration has obviously also enough because we were able to create the groups. Just adding this azure ad group to the azure devops project groups doesn't work using the PAT and the Rest API.

The script which we are using:

while(!$tenantID) {  
 Write-Host "Please provide tentant id:"  
 $tenantID = Read-Host  
 Write-Host ""  
}  
  
while(!$organization) {  
 Write-Host "Please provide organization:"  
 $organization = Read-Host  
 Write-Host ""  
}  
  
while(!$projectName) {  
 Write-Host "Please provide Project name:"  
 $projectName = Read-Host  
 Write-Host ""  
}  
  
while(!$projectDescription) {  
 Write-Host "Please provide project description:"  
 $projectDescription = Read-Host  
 Write-Host ""  
}  
  
while(!$clientID) {  
 Write-Host "Please provide client id:"  
 $clientID = Read-Host  
 Write-Host ""  
}  
  
while(!$clientSecret) {  
 Write-Host "Please provide client secret:"  
 $clientSecret = Read-Host  
 Write-Host ""  
}  
  
while(!$PAT) {  
 Write-Host "Please provide personal access token:"  
 $PAT = Read-Host  
 Write-Host ""  
}  
  
  
#Get Graph API Access Token  
$body = @{  
 "grant_type" = "client_credentials"  
 "client_id" = $clientID  
 "client_secret" = $clientSecret  
 "scope" = "https://graph.microsoft.com/.default"  
}  
  
try {  
 $response = Invoke-WebRequest -Method "POST" -URI "https://login.microsoftonline.com/$($tenantID)/oauth2/v2.0/token" -Body $body  
 $graphApiToken = (ConvertFrom-Json $response.Content).access_token  
 if(!$graphApiToken){  
 throw "Error retrieving Graph API Access Token"  
 }  
} catch {  
 throw $_.Exception.Message  
}  
  
  
$devopsApiHeaders = @{  
 Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($PAT)"))  
 "Content-type" = "application/json"  
}  
  
#Check for existing Project  
try {  
 $response = Invoke-WebRequest -Method "GET" -URI "https://dev.azure.com/$($organization)/_apis/projects/$($projectName)?api-version=7.0-preview.1" -Headers $devopsApiHeaders  
 if($response.StatusCode -eq 200) {  
 throw "Project already exists"  
 }  
} catch {  
 if($_.Exception.Response.StatusCode.Value__ -ne 404) {  
 throw "Error reading existing Projects"  
 }  
}  
  
#Create new project  
try {  
 $body = @{  
 "name" = $projectName  
 "description" = $projectDescription  
 "capabilities" = @{  
 "versioncontrol" = @{  
 "sourceControlType" = "Git"  
 }  
 "processTemplate" = @{  
   "templateTypeId" = "6b724908-ef14-45cf-84f8-768b5384da45"  
 }  
 }  
 }  
 $response = Invoke-WebRequest -Method "POST" -URI "https://dev.azure.com/$($organization)/_apis/projects?api-version=7.0" -Body (ConvertTo-Json $body) -Headers $devopsApiHeaders  
  
 if($response.StatusCode -ne 202) {  
 throw "Error creating project"  
 }  
 start-sleep -s 5  
 $response = Invoke-WebRequest -Method "GET" -URI "https://dev.azure.com/$($organization)/_apis/projects/$($projectName)?api-version=7.0" -Headers $devopsApiHeaders  
 $projectId = (ConvertFrom-Json $response.Content).id  
  
  
 Write-Host "Project $projectName created"  
} catch {  
 throw "Error creating project"  
}  
  
#Create groups  
$prefix = "G_AZDEVOPS_P"  
$groups = @("Project Administrators","Contributors")  
  
$graphApiHeaders = @{  
 Authorization = "Bearer $graphApiToken"  
 "Content-type" = "application/json"  
}  
  
foreach($group in $groups) {  
 $groupName = "$($prefix)_$($group.replace(' ',''))_$($projectName.replace(' ',''))"  
 $description = "$group for project $projectName"  
 $body = @{  
 "displayName" = $groupName  
 "description" = $description  
 "mailEnabled" = $false  
 "securityEnabled" = $true  
 "mailNickname" = $groupName  
 }  
 try {  
 $response = Invoke-WebRequest -Method "POST" -URI "https://graph.microsoft.com/v1.0/groups" -Body (ConvertTo-Json $body) -Headers $graphApiHeaders  
 $AADGroupId = (ConvertFrom-Json $response.Content).id  
 Write-Host "Group $groupName created"  
 } catch {  
       Write-Error $Error[0]  
 continue  
 }  
 try {  
 if($response.StatusCode -eq 201) {  
 $projectDescriptor = (ConvertFrom-Json (Invoke-WebRequest -Method "GET" -URI "https://vssps.dev.azure.com/$($organization)/_apis/graph/descriptors/$($projectId)?api-version=7.0-preview.1" -Headers $devopsApiHeaders).Content).value  
 $projectGroups = (ConvertFrom-Json (invoke-WebRequest -Method Get -uri "https://vssps.dev.azure.com/$($organization)/_apis/graph/groups?scopeDescriptor=$projectDescriptor&api-version=7.0-preview.1"-Headers $devopsApiHeaders).Content).value  
  
 $groupDescriptior = ($projectGroups | Where-Object displayName -eq $group).descriptor  
  
 $body = @{  
 originId = $AADGroupId  
 }  
  
 Invoke-RestMethod -Method Post -Uri "https://vssps.dev.azure.com/vipps/_apis/graph/groups?groupDescriptors=$groupDescriptior&api-version=6.0-preview.1" -Body (ConvertTo-Json $body) -Headers $devopsApiHeaders  
 Write-Host "Permission added for group $groupName"  
 }  
 }  catch {  
 Write-Error $Error[0]  
 continue  
 }  
}  
  
Read-Host  

So on the last try and catch which should add the permissions we are getting this error: 'The remote server returned an error: (401) Unauthorized.'.

Not Monitored
Not Monitored
Tag not monitored by Microsoft.
37,573 questions
0 comments No comments
{count} votes

Accepted answer
  1. Anonymous
    2022-11-23T19:25:45.067+00:00

    Devops / TFS is not currently supported here on Q&A. The product group for Azure DevOps / TFS actively monitors questions over at
    https://developercommunity.visualstudio.com/report?space=21&entry=problem
    https://developercommunity.visualstudio.com/report?space=22&entry=problem
    https://azure.microsoft.com/en-in/support/devops/

    --please don't forget to upvote and Accept as answer if the reply is helpful--

    0 comments No comments

0 additional answers

Sort by: Most helpful