powershellazure-app-registration

Unable to use powershell to set empty array on app registration manifest for API permissions


I'm trying to write a powershell script to remove delegated permissions from my app registrations on Azure. I'm able to successfully do this if there is any application type permissions but when trying to remove all delegated permissions from app registrations with application permissions

Eg from this:

    "requiredResourceAccess": [
    {
        "resourceAppId": "00000003-0000-0000-c000-000000000000",
        "resourceAccess": [
            {
                "id": "64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0",
                "type": "Scope"
            }
        ]
    }
],

To this:

        "requiredResourceAccess": [],

This doesn't seem to work via powershell using @() but does via the portal.

Here is my powershell script to test this:

Connect-MgGraph -Scopes "Application.ReadWrite.All" -TenantId "XXX"
$dummyPermission = @()

$appId = "XXX" # Define your App ID

$appManifest = Get-MgApplication -ApplicationId $appId
Write-Host "Original RequiredResourceAccess count: $($appManifest.RequiredResourceAccess.Count)" -ForegroundColor Yellow
Update-MgApplication -ApplicationId $appId -RequiredResourceAccess $dummyPermission
$app.RequiredResourceAccess | ConvertTo-Json -Depth 3

EDIT:

This is an update after the answer for a functioning example is there anyway I can make this more efficient:

  1. Authenticate
  2. Remove admin access grant
  3. Checks for all of the NON scoped/delegated permissions
  4. If there are NON scoped/delegated permissions then the manifest is updated with the role/application permissions
  5. If there aren't any then the block is set to be an empty array to remove all permissions

Code:

function main {
    $TenantId = "XXX"

    $Parameters = @{
        TenantId = $TenantId}

    Remove-ManifestPermissions @Parameters
}

function Remove-ManifestPermissions
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [Guid]
        $TenantId
    )

    $requiredScopes = @(
        "Application.ReadWrite.All",
        "DelegatedPermissionGrant.ReadWrite.All"
    )

    $null = Connect-MgGraph -Scopes $requiredScopes -TenantId $TenantId

    $apps = Get-MgApplication -All

    foreach ($app in $apps)
    {
        # Get the service principal associated with the app
        $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$($app.AppId)'"
        $apiPermissions = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipal $servicePrincipal.Id
        foreach ($perm in $apiPermissions)
        {
            # Remove Admin Access Grant
            Write-Host " - Found $( $perm.Count ) Delegated Permission (Removing...)"
            Remove-MgOauth2PermissionGrant -Oauth2PermissionGrantId $perm.Id
        }

        Write-Host "Reviewing App: $( $app.DisplayName )"
        $appManifest = Get-MgApplication -ApplicationId $app.Id

        if ($appManifest.RequiredResourceAccess[0].ResourceAccess)
        {
            Write-Host "Processing ResourceAppId: $( $app.DisplayName ) with $( $appManifest.RequiredResourceAccess[0].ResourceAccess.Count ) API Permissions."
            $appManifest.RequiredResourceAccess[0].ResourceAccess = $appManifest.RequiredResourceAccess[0].ResourceAccess | Where-Object { $_.Type -ne 'Scope' }

            if ($appManifest.RequiredResourceAccess[0].ResourceAccess.Count -gt 0)
            {
                Update-MgApplication -ApplicationId $app.Id -RequiredResourceAccess $appManifest.RequiredResourceAccess
                Write-Host "$( $app.DisplayName ) has $( $appManifest.RequiredResourceAccess[0].ResourceAccess.Count ) API Permission(s) remaining."
            }

            # If all API Permissions are delegated permissions, remove the RequiredResourceAccess entry
            elseif ($appManifest.RequiredResourceAccess[0].ResourceAccess.Count -eq 0)
            {
                $uri = "https://graph.microsoft.com/v1.0/applications/$($app.Id)"
                $body = @{
                    requiredResourceAccess = @()
                } | ConvertTo-Json -Depth 3

                Invoke-MgGraphRequest -Method PATCH -Uri $uri -Body $body -ContentType "application/json"
            }

            # Update the manifest if there are role type API permissions
            Write-Host "No Delegated Permissions remain for $( $app.DisplayName )"
        }
        else
        {
            Write-Host "No API Permissions found for $( $app.DisplayName )"
        }
    }
    Disconnect-MgGraph | Out-Null
}
main

Solution

  • Note: There is no direct PowerShell command to set requiredResourceAccess as null.

    Hence you can make use of Microsoft Graph API to set requiredResourceAccess as null:

    For sample, I added application and delegated API permissions:

    enter image description here

    First you need to revoke admin consent granted to the permissions:

    enter image description here

    Make use of below query:

    PATCH https://graph.microsoft.com/v1.0/applications/ObjectID
    
    {
    "requiredResourceAccess": []
    }
    

    enter image description here

    Now when I refresh the Portal the API permissions are removed and manifest is set as requiredResourceAccess : []

    enter image description here

    enter image description here

    Alternatively, you can also make use of below PowerShell script:

    Connect-MgGraph -Scopes "Application.ReadWrite.All"
    
    $uri = "https://graph.microsoft.com/v1.0/applications/ObjectID"
    $body = @{
        requiredResourceAccess = @()
    } | ConvertTo-Json -Depth 3
    
    Invoke-MgGraphRequest -Method PATCH -Uri $uri -Body $body -ContentType "application/json"
    

    enter image description here

    Reference:

    Graph API - Can you remove all permissions from your own app via api call? - Microsoft Q&A by JanardhanaVedham-MSFT