Share via


Ingetrokken machtigingen herstellen die zijn verleend aan toepassingen

In dit artikel leert u hoe u eerder ingetrokken machtigingen herstelt die zijn verleend aan een toepassing. U kunt machtigingen herstellen voor een toepassing waaraan machtigingen zijn verleend voor toegang tot de gegevens van uw organisatie. U kunt ook machtigingen herstellen voor een toepassing waaraan machtigingen zijn verleend om als gebruiker te fungeren.

Op dit moment is het herstellen van machtigingen alleen mogelijk via Microsoft Graph PowerShell en Microsoft Graph API-aanroepen. U kunt geen machtigingen herstellen via het Microsoft Entra-beheercentrum. In dit artikel leert u hoe u machtigingen herstelt met Behulp van Microsoft Graph PowerShell.

Vereisten

Als u eerder ingetrokken machtigingen voor een toepassing wilt herstellen, hebt u het volgende nodig:

  • Een Azure-account met een actief abonnement. Gratis een account maken
  • Een van de volgende rollen: Cloud Application Beheer istrator, Application Beheer istrator.
  • Een Service-principal-eigenaar die geen beheerder is, kan vernieuwingstokens ongeldig maken.

Ingetrokken machtigingen voor een toepassing herstellen

U kunt verschillende methoden proberen voor het herstellen van machtigingen:

  • Gebruik de knop Beheerderstoestemming verlenen op de pagina Machtigingen voor de app om toestemming opnieuw toe te passen. Met deze toestemming wordt de set machtigingen toegepast die de ontwikkelaar van de app oorspronkelijk heeft aangevraagd in het app-manifest.

Notitie

Het intrekken van beheerderstoestemming verwijdert alle verleende machtigingen die geen deel uitmaken van de standaardset die door de ontwikkelaar is geconfigureerd.

  • Als u weet welke specifieke machtiging is ingetrokken, kunt u deze opnieuw handmatig verlenen met behulp van PowerShell of de Microsoft Graph API.
  • Als u de ingetrokken machtigingen niet weet, kunt u de scripts in dit artikel gebruiken om ingetrokken machtigingen te detecteren en terug te zetten.

Stel eerst de waarde servicePrincipalId in het script in op de id-waarde voor de bedrijfs-app waarvan u de machtigingen wilt herstellen. Deze id wordt ook wel de object ID pagina bedrijfstoepassingen van het Microsoft Entra-beheercentrum genoemd.

Voer vervolgens elk script uit om $ForceGrantUpdate = $false een lijst met gedelegeerde of alleen-app-machtigingen te zien die mogelijk zijn verwijderd. Zelfs als de machtigingen al zijn hersteld, worden er mogelijk nog steeds gebeurtenissen uit uw auditlogboeken ingetrokken in de scriptresultaten.

Laat $ForceGrantUpdate deze optie ingesteld als $true u wilt dat het script probeert om ingetrokken machtigingen te herstellen die worden gedetecteerd. De scripts vragen om bevestiging, maar vragen niet om afzonderlijke goedkeuring voor elke machtiging die wordt hersteld.

Wees voorzichtig bij het verlenen van machtigingen aan apps. Zie Machtigingen evalueren voor meer informatie over het evalueren van machtigingen.

Gedelegeerde machtigingen herstellen

# WARNING: Setting $ForceGrantUpdate to true will modify permission grants without
# prompting for confirmation. This can result in unintended changes to your
# application's security settings. Use with caution!
$ForceGrantUpdate = $false

# Set the start and end dates for the audit log search
# If setting date use yyyy-MM-dd format
# endDate is set to tomorrow to include today's audit logs
$startDate = (Get-Date).AddDays(-7).ToString('yyyy-MM-dd')
$endDate = (Get-Date).AddDays(1).ToString('yyyy-MM-dd')

# Set the service principal ID
$servicePrincipalId = "aaaaaaaa-bbbb-cccc-1111-222222222222"

Write-Host "Searching for audit logs between $startDate and $endDate" -ForegroundColor Green
Write-Host "Searching for audit logs for service principal $servicePrincipalId" -ForegroundColor Green

if ($ForceGrantUpdate -eq $true) {
    Write-Host "WARNING: ForceGrantUpdate is set to true. This will modify permission grants without prompting for confirmation. This can result in unintended changes to your application's security settings. Use with caution!" -ForegroundColor Red
    $continue = Read-Host "Do you want to continue? (Y/N)"
    if ($continue -eq "Y" -or $continue -eq "y") {
        Write-Host "Continuing..."
    } else {
        Write-Host "Exiting..."
        exit
    }
}

# Connect to MS Graph
Connect-MgGraph -Scopes "AuditLog.Read.All","DelegatedPermissionGrant.ReadWrite.All" -ErrorAction Stop | Out-Null

# Create a hashtable to store the OAuth2PermissionGrants
$oAuth2PermissionGrants = @{}

function Merge-Scopes($oldScopes, $newScopes) {
    $oldScopes = $oldScopes.Trim() -split '\s+'
    $newScopes = $newScopes.Trim() -split '\s+'
    $mergedScopesArray = $oldScopes + $newScopes | Select-Object -Unique
    $mergedScopes = $mergedScopesArray -join ' '
    return $mergedScopes.Trim()
}

# Function to merge scopes if multiple OAuth2PermissionGrants are found in the audit logs
function Add-Scopes($resourceId, $newScopes) {
    if($oAuth2PermissionGrants.ContainsKey($resourceId)) {
        $oldScopes = $oAuth2PermissionGrants[$resourceId]
        $oAuth2PermissionGrants[$resourceId] = Merge-Scopes $oldScopes $newScopes
    }
    else {
        $oAuth2PermissionGrants[$resourceId] = $newScopes
    }
}

function Get-ScopeDifference ($generatedScope, $currentScope) {
    $generatedScopeArray = $generatedScope.Trim() -split '\s+'
    $currentScopeArray = $currentScope.Trim() -split '\s+'
    $difference = $generatedScopeArray | Where-Object { $_ -notin $currentScopeArray }
    $difference = $difference -join ' '
    return $difference.Trim()
}

# Set the filter for the audit log search
$filterOAuth2PermissionGrant = "activityDateTime ge $startDate and activityDateTime le $endDate" +
    " and Result eq 'success'" +
    " and ActivityDisplayName eq 'Remove delegated permission grant'" +
    " and targetResources/any(x: x/id eq '$servicePrincipalId')"
try {
    # Retrieve the audit logs for removed OAuth2PermissionGrants
    $oAuth2PermissionGrantsAuditLogs = Get-MgAuditLogDirectoryAudit -Filter $filterOAuth2PermissionGrant -All -ErrorAction Stop
}
catch {
    Disconnect-MgGraph | Out-Null
    throw $_
}

# Remove User Delegated Permission Grants
$oAuth2PermissionGrantsAuditLogs = $oAuth2PermissionGrantsAuditLogs | Where-Object {
    -not ($_.TargetResources.ModifiedProperties.OldValue -eq '"Principal"')
}

# Merge duplicate OAuth2PermissionGrants from AuditLogs using Add-Scopes
foreach ($auditLog in $oAuth2PermissionGrantsAuditLogs) {
    $resourceId = $auditLog.TargetResources[0].Id
    # We only want to process OAuth2PermissionGrant Audit Logs where $servicePrincipalId is the clientId not the resourceId
    if ($resourceId -eq $servicePrincipalId) {
        continue
    }
    $oldScope = $auditLog.TargetResources[0].ModifiedProperties | Where-Object { $_.DisplayName -eq "DelegatedPermissionGrant.Scope" } | Select-Object -ExpandProperty OldValue
    if ($oldScope -eq $null) {
        $oldScope = ""
    }
    $oldScope = $oldScope.Replace('"', '')
    $newScope = $auditLog.TargetResources[0].ModifiedProperties | Where-Object { $_.DisplayName -eq "DelegatedPermissionGrant.Scope" } | Select-Object -ExpandProperty NewValue
    if ($newScope -eq $null) {
        $newScope = ""
    }
    $newScope = $newScope.Replace('"', '')
    $scope = Merge-Scopes $oldScope $newScope
    Add-Scopes $resourceId $scope
}

$permissionCount = 0
foreach ($resourceId in $oAuth2PermissionGrants.keys) {
    $scope = $oAuth2PermissionGrants[$resourceId]
    $params = @{
        clientId = $servicePrincipalId
        consentType = "AllPrincipals"
        resourceId = $resourceId
        scope = $scope
    }

    try {
        $currentOAuth2PermissionGrant = Get-MgOauth2PermissionGrant -Filter "clientId eq '$servicePrincipalId' and consentType eq 'AllPrincipals' and resourceId eq '$resourceId'" -ErrorAction Stop
        $action = "Creating"
        if ($currentOAuth2PermissionGrant -ne $null) {
            $action = "Updating"
        }
        Write-Host "--------------------------"
        if ($ForceGrantUpdate -eq $true) {
            Write-Host "$action OAuth2PermissionGrant with the following parameters:"
        } else {
            Write-Host "Potentially removed OAuth2PermissionGrant scopes with the following parameters:"
        }
        Write-Host "    clientId: $($params.clientId)"
        Write-Host "    consentType: $($params.consentType)"
        Write-Host "    resourceId: $($params.resourceId)"
        if ($currentOAuth2PermissionGrant -ne $null) {
            $scopeDifference = Get-ScopeDifference $scope $currentOAuth2PermissionGrant.Scope
            if ($scopeDifference -eq "") {
                Write-Host "OAuth2PermissionGrant already exists with the same scope" -ForegroundColor Yellow
                if ($ForceGrantUpdate -eq $true) {
                    Write-Host "Skipping Update" -ForegroundColor Yellow
                }
                continue
            }
            else {
                Write-Host "    scope diff: '$scopeDifference'"
            }
        }
        else {
            Write-Host "    scope: '$($params.scope)'"
        }
        if ($ForceGrantUpdate -eq $true -and $currentOAuth2PermissionGrant -eq $null) {
            New-MgOauth2PermissionGrant -BodyParameter $params -ErrorAction Stop | Out-Null
            Write-Host "OAuth2PermissionGrant was created successfully" -ForegroundColor Green
        }
        if ($ForceGrantUpdate -eq $true -and $currentOAuth2PermissionGrant -ne $null) {
            Write-Host "    Current Scope: '$($currentOAuth2PermissionGrant.scope)'" -ForegroundColor Yellow
            Write-Host "    Merging with scopes from audit logs" -ForegroundColor Yellow
            $params.scope = Merge-Scopes $currentOAuth2PermissionGrant.scope $params.scope
            Write-Host "    New Scope: '$($params.scope)'" -ForegroundColor Yellow
            Update-MgOauth2PermissionGrant -OAuth2PermissionGrantId $currentOAuth2PermissionGrant.id -BodyParameter $params -ErrorAction Stop | Out-Null
            Write-Host "OAuth2PermissionGrant was updated successfully" -ForegroundColor Green
        }
        $permissionCount++
    }
    catch {
        Disconnect-MgGraph | Out-Null
        throw $_
    }
}

Disconnect-MgGraph | Out-Null

if ($ForceGrantUpdate -eq $true) {
    Write-Host "--------------------------"
    Write-Host "$permissionCount OAuth2PermissionGrants were created/updated successfully" -ForegroundColor Green
} else {
    Write-Host "--------------------------"
    Write-Host "$permissionCount OAuth2PermissionGrants were found" -ForegroundColor Green
}

Machtigingen voor alleen apps herstellen

Notitie

Voor het verlenen van alleen-app-machtigingen aan Microsoft Graph is de rol Bevoorrechte rol Beheer istrator vereist.

# WARNING: Setting $ForceGrantUpdate to true will modify permission grants without
# prompting for confirmation. This can result in unintended changes to your
# application's security settings. Use with caution!
$ForceGrantUpdate = $false

# Set the start and end dates for the audit log search
# If setting date use yyyy-MM-dd format
# endDate is set to tomorrow to include today's audit logs
$startDate = (Get-Date).AddDays(-7).ToString('yyyy-MM-dd')
$endDate = (Get-Date).AddDays(1).ToString('yyyy-MM-dd')

# Set the service principal ID
$servicePrincipalId = "aaaaaaaa-bbbb-cccc-1111-222222222222"

Write-Host "Searching for audit logs between $startDate and $endDate" -ForegroundColor Green
Write-Host "Searching for audit logs for service principal $servicePrincipalId" -ForegroundColor Green

if ($ForceGrantUpdate -eq $true) {
    Write-Host "WARNING: ForceGrantUpdate is set to true. This will modify permission grants without prompting for confirmation. This can result in unintended changes to your application's security settings. Use with caution!" -ForegroundColor Red
    $continue = Read-Host "Do you want to continue? (Y/N)"
    if ($continue -eq "Y" -or $continue -eq "y") {
        Write-Host "Continuing..."
    } else {
        Write-Host "Exiting..."
        exit
    }
}

# Connect to MS Graph
Connect-MgGraph -Scopes "AuditLog.Read.All","Application.Read.All","AppRoleAssignment.ReadWrite.All" -ErrorAction Stop | Out-Null

# Set the filter for the audit log search
$filterAppRoleAssignment = "activityDateTime ge $startDate and activityDateTime le $endDate" + 
    " and Result eq 'success'" +
    " and ActivityDisplayName eq 'Remove app role assignment from service principal'" +
    " and targetResources/any(x: x/id eq '$servicePrincipalId')"

try {
    # Retrieve the audit logs for removed AppRoleAssignments
    $appRoleAssignmentsAuditLogs = Get-MgAuditLogDirectoryAudit -Filter $filterAppRoleAssignment -All -ErrorAction Stop
}
catch {
    Disconnect-MgGraph | Out-Null
    throw $_
}

$permissionCount = 0
foreach ($auditLog in $appRoleAssignmentsAuditLogs) {
    $resourceId = $auditLog.TargetResources[0].Id
    # We only want to process AppRoleAssignments Audit Logs where $servicePrincipalId is the principalId not the resourceId
    if ($resourceId -eq $servicePrincipalId) {
        continue
    }
    $appRoleId = $auditLog.TargetResources[0].ModifiedProperties | Where-Object { $_.DisplayName -eq "AppRole.Id" } | Select-Object -ExpandProperty OldValue
    $appRoleId = $appRoleId.Replace('"', '')
    $params = @{
        principalId = $servicePrincipalId
        resourceId = $resourceId
        appRoleId = $appRoleId
    }

    try {
        $sp = Get-MgServicePrincipal -ServicePrincipalId $resourceId
        $appRole = $sp.AppRoles | Where-Object { $_.Id -eq $appRoleId }

        Write-Host "--------------------------"
        if ($ForceGrantUpdate -eq $true) {
            Write-Host "Creating AppRoleAssignment with the following parameters:"
        } else {
            Write-Host "Potentially removed AppRoleAssignment with the following parameters:"
        }
        Write-Host "    principalId: $($params.principalId)"
        Write-Host "    resourceId: $($params.resourceId)"
        Write-Host "    appRoleId: $($params.appRoleId)"
        Write-Host "    appRoleValue: $($appRole.Value)"
        Write-Host "    appRoleDisplayName: $($appRole.DisplayName)"
        if ($ForceGrantUpdate -eq $true) {
            New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $servicePrincipalId -BodyParameter $params -ErrorAction Stop | Out-Null
            Write-Host "AppRoleAssignment was created successfully" -ForegroundColor Green
        }
        $permissionCount++
    }
    catch {
        if ($_.Exception.Message -like "*Permission being assigned already exists on the object*") {
            Write-Host "AppRoleAssignment already exists skipping creation" -ForegroundColor Yellow
        }
        else {
            Disconnect-MgGraph | Out-Null
            throw $_
        }
    }
}

Disconnect-MgGraph | Out-Null

if ($ForceGrantUpdate -eq $true) {
    Write-Host "--------------------------"
    Write-Host "$permissionCount AppRoleAssignments were created successfully" -ForegroundColor Green
} else {
    Write-Host "--------------------------"
    Write-Host "$permissionCount AppRoleAssignments were found" -ForegroundColor Green
}