Search code examples
powershellazure-devopsazure-powershell

Insufficient Permissions 403 for Add-MgApplicationPassword Powershell


In an Azure Devops pipeline, I am trying to run a Azure Powershell script which would create an app registration and then generate a client secret for that created app.

The service principal behind the service connection running this script has "Application Developer" built in role.

Problem: The app registration gets created but the client secret generation fails saying "

Add-MgApplicationPassword_Add: /home/vsts/work/1/drop/pipelines/scripts/AppRegistrationDeployment.ps1:73
Line |
  73 |          Add-MgApplicationPassword -ApplicationId $applicationId -Body …
     |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Insufficient privileges to complete the operation.  Status: 403
     | (Forbidden) ErrorCode: Authorization_RequestDenied

The created app has the SPN running the script (the one behind the service connection) as the Owner, so I am unsure why does it fail with insufficient permissions.

This is how I connect to Microsoft graph

    Import-Module Microsoft.Graph.Applications

    $context = Get-AzContext
    $graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.microsoft.com").AccessToken
    
    $secureGraphToken = $graphToken | ConvertTo-SecureString -AsPlainText -Force
    Connect-MgGraph -AccessToken $secureGraphToken

this works

$createAppBody = @{
                displayName = $AppRegistrationName
            }
$appreg = New-MgApplication -BodyParameter $createAppBody

However this fails with insufficient permissions

$clientSecretBody = @{
            passwordCredential = @{
                displayName = "$secretNamePrefix-$secretSuffix"
                endDateTime = $secretEndDate
            }
        }
Add-MgApplicationPassword -ApplicationId $applicationId -BodyParameter $clientSecretBody

As mentioned on the created app, I see the SPN running the script ( a service connection) as the Owner of the created app.

Why would an owner not be able to create a secret, when it can create the app itself?

Any questions and I can answer.

P.s I have already tried

Disconnect-MgGraph

and then try to re-initialize the token again but to no avail.


Solution

  • The error occured as Application Developer role does not have microsoft.directory/applications/credentials/update permission to create credentials(secret) in it.

    I assigned Application Developer role to the service principal named SriGraphRole:

    enter image description here

    When I ran below PowerShell commands to create application and secret in it, I too got same error:

    $secureGraphToken = $graphToken | ConvertTo-SecureString -AsPlainText -Force
    Connect-MgGraph -AccessToken $secureGraphToken
    Import-Module Microsoft.Graph.Applications
    
    $app = New-MgApplication -DisplayName 'NewMGapp'
    $params = @{
        PasswordCredential = @{
            DisplayName = "secret"
        }
    }
    Add-MgApplicationPassword -ApplicationId $app.Id -BodyParameter $params
    

    Response:

    enter image description here

    To resolve the error, your service principal should be assigned with either required API permission or Azure AD directory role having microsoft.directory/applications/credentials/update action.

    In my case, I assigned Application Administrator role to the service principal named SriGraphRole:

    enter image description here

    When I ran below PowerShell script again, new application with secret created successfully like below:

    $secureGraphToken = $graphToken | ConvertTo-SecureString -AsPlainText -Force
    Connect-MgGraph -AccessToken $secureGraphToken
    Import-Module Microsoft.Graph.Applications
    
    $app = New-MgApplication -DisplayName 'NewMGapp'
    $params = @{
        PasswordCredential = @{
            DisplayName = "secret"
        }
    }
    Add-MgApplicationPassword -ApplicationId $app.Id -BodyParameter $params
    

    Response:

    enter image description here

    To confirm that, I checked the same in Portal where new application with secret created:

    enter image description here

    When the user is added as Owner of application, he can create secrets without any extra permissions as Application Owner of user type has microsoft.directory/applications/credentials/update action access added by default as mentioned in this MS Document.

    But same is not applicable for application scenario and it requires Application.ReadWrite.Ownedby API permission that works only if service principal is Owner of application which is an in-built action.