0

When using the https://graph.microsoft.com/.default API to PATCH an Application in Azure AD it fails with the error:

"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.", ...

The call authenticates by Application permissions and the following are configured: Application.ReadWrite.All, Directory.ReadWrite.All.

$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token";
$resourceUrl = 'https://graph.microsoft.com/.default'

$body = @{ grant_type='client_credentials';client_id=$clientId;client_secret=$clientSecret;scope=$resourceUrl; }
$result = Invoke-RestMethod -Method Post -Uri $uri -Body $body
$accessToken = $result.access_token
$authHeader = "Bearer $accessToken"

$patchBody = '{
  "displayName" : "dev2"
}'

Invoke-RestMethod -method PATCH -Uri https://graph.microsoft.com/v1.0/applications/$($app.Id) -Body $patchBody -ContentType application/json -Headers @{Authorization = $AuthHeader }

Here is the API permission:

Application API permissions Note: I do have access to perform a GET operation for the Application.

Is it possible to achieve this?

user3167162
  • 445
  • 1
  • 6
  • 23

1 Answers1

0

The Application permission Application.ReadWrite.All is enough, make sure you grant it in Microsoft Graph, not Azure Active Directory Graph, and don't forget to click the Grant admin consent button.

enter image description here

In your script, you should not pass the $body in the last line, the $body is used to get access token. And make sure this part $($app.Id) is the ObjectId of the application.

$body = @{ grant_type='client_credentials';client_id=$clientId;client_secret=$clientSecret;scope=$resourceUrl; }

Invoke-RestMethod -method PATCH -Uri https://graph.microsoft.com/v1.0/applications/$($app.Id) -Body $body -ContentType application/json -Headers @{Authorization = $AuthHeader }

You need to use the body in this link Update application - Request body, you could store it in the .json file, then use Get-Content to get it.

In my sample, I update the appRoles, you could refer to it as below.

The patch.json file:

{
 "appRoles": [
   {
    "allowedMemberTypes": [
      "User"
    ],
    "description": "Creators can create Surveys",
    "displayName": "SurveyCreator",
    "id": "1b4f816e-5eaf-48b9-8613-7923830595ad",
    "isEnabled": false,
    "value": "SurveyCreator"
  }
 ]
}

Script:

$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token";
$resourceUrl = 'https://graph.microsoft.com/.default'

$body = @{ grant_type='client_credentials';client_id=$clientId;client_secret=$clientSecret;scope=$resourceUrl; }
$result = Invoke-RestMethod -Method Post -Uri $uri -Body $body
$accessToken = $result.access_token
$authHeader = "Bearer $accessToken"

$body1 = Get-Content -Path "C:\Users\joyw\Desktop\patch.json"

Invoke-RestMethod -method PATCH -Uri https://graph.microsoft.com/v1.0/applications/<Object-id> -Body $body1 -ContentType application/json -Headers @{Authorization = $AuthHeader }

After running the command, you could use GET method to check the result.

Invoke-RestMethod -method GET -Uri https://graph.microsoft.com/v1.0/applications/<Object-id> -ContentType application/json -Headers @{Authorization = $AuthHeader }

enter image description here

Update:

If you use this as the body, it will also work.

$patchBody = '{
  "displayName" : "dev2"
}'

enter image description here

Joy Wang
  • 39,905
  • 3
  • 30
  • 54
  • thanks for your response. I am using Application.ReadWrite.All for Microsoft Graph, and JSON in the PATCH body although I missed it in my original code snippet. I get the access error. – user3167162 Jan 07 '20 at 06:26
  • @user3167162 See my update. Was the error fixed now? – Joy Wang Jan 07 '20 at 06:28
  • @user3167162 Could you show the `API permissions` page of your AD app which you used to get the token in your question? – Joy Wang Jan 07 '20 at 06:32
  • Sure, I added it in the question. – user3167162 Jan 07 '20 at 06:35
  • @user3167162 The permission is right. Could you decode the token in the https://jwt.io/, and see if the `Application.ReadWrite.All` is included in the `roles`? Refer to the screenshot - https://i.stack.imgur.com/fcuer.png – Joy Wang Jan 07 '20 at 06:40
  • Application.ReadWrite.All is included in the token. – user3167162 Jan 07 '20 at 06:43
  • @user3167162 Does this part `$($app.Id)` be the object-id of another app? – Joy Wang Jan 07 '20 at 06:46
  • No, it's the same App, I retrieved from the API: (Invoke-RestMethod -method GET -Uri "https://graph.microsoft.com/v1.0/applications/" -Headers @{ Authorization = $authHeader }).Value | ? { $_.AppId -eq $clientId } – user3167162 Jan 07 '20 at 06:48
  • @user3167162 It's so weird, could you create a new app to have a try? All work fine on my side. Just give the only `Application.ReadWrite.All` permission. – Joy Wang Jan 07 '20 at 07:04
  • I cleared out several other API permissions I had configured in addition Application.ReadWrite.All to and it now seems to work. I'm going to try and reproduce it again to verify this was a cause. – user3167162 Jan 07 '20 at 07:07
  • It fails when the ```Application.Read.All``` permission is added to the list. I guess this is a bug. Thanks you were very helpful. – user3167162 Jan 07 '20 at 07:11
  • @user3167162 I also have a test with adding the `Application.Read.All`, it also works fine. It seems not to be the cause. I think you can try to revoke all the permissions and grant the `Application.ReadWrite.All` again or create a new app. – Joy Wang Jan 07 '20 at 07:20
  • @user3167162 Glad it works now, if my reply is helpful, please accept it, thanks.:-) – Joy Wang Jan 07 '20 at 07:23
  • @user3167162 Hi, any other concern? – Joy Wang Jan 08 '20 at 07:25
  • Hi @joywang can you reproduce it by adding the ```Application.ReadWrite.OwnedBy``` permission? – user3167162 Jan 09 '20 at 02:41
  • @user3167162 Incredible, I reproduced the error, maybe a bug. I also decode the token, the `Application.ReadWrite.All` is included. – Joy Wang Jan 09 '20 at 02:55