0

I have got the code below, its running with the context of an application account. Runs fine when it runs on the context of an interactive user when setting the following scopes.

$scopes = @(
    "PrivilegedAccess.Read.AzureAD",
    "RoleAssignmentSchedule.ReadWrite.Directory", 
    "PrivilegedAccess.ReadWrite.AzureAD", 
    "User.Read.All"
)

Connect-MgGraph -Scopes $scopes

However since the context of the execution is an application, its not possible to set scopes.

The full code is as follows.

    # Set the target user
    $user = "[email protected]"
    
    # Get the Object ID for the user

$userObj = Get-MgUser -UserId $user -ErrorAction Stop
$objectId = $userObj.Id
Write-Host "User Object ID for $user is $objectId"

# Get all pending PIM requests
[array]$pendingApprovals = Invoke-GraphRequest `
    -Method GET `
    -Uri "/beta/roleManagement/directory/roleAssignmentScheduleRequests?`$filter=status eq 'PendingApproval'" |
    Select-Object -ExpandProperty value

# Filter only those for the specified user
$userApprovals = $pendingApprovals | Where-Object { $_.principalId -eq $objectId }

if (-not $userApprovals) {
    Write-Host "No pending approvals found for $user"
    return
}

foreach ($approvalRequest in $userApprovals) {
    $approvalId = $approvalRequest.approvalId

    # Get the approval steps
    $steps = Invoke-GraphRequest `
        -Method GET `
        -Uri "/beta/roleManagement/directory/roleAssignmentApprovals/$approvalId" |
        Select-Object -ExpandProperty steps

    $pendingStep = $steps | Where-Object { $_.status -eq "InProgress" }

    if ($pendingStep) {
        $stepId = $pendingStep.id
        $body = @{
            reviewResult  = "Approve"
            justification = "Auto-approved for $user on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') via Automation"
        }

        Write-Host "Approving step $stepId for request $approvalId"

        Invoke-GraphRequest `
            -Method PATCH `
            -Uri "https://graph.microsoft.com/beta/roleManagement/directory/roleAssignmentApprovals/$approvalId/steps/$stepId" `
            -Body $body
    } else {
        Write-Host "No 'InProgress' approval step found for request $approvalId"
    }
}

Its currently failing with the section below.

Invoke-GraphRequest `
    -Method PATCH `
    -Uri "https://graph.microsoft.com/beta/roleManagement/directory/roleAssignmentApprovals/$approvalId/steps/$stepId" `
    -Body $body

The error is as follows

   | PATCH https://graph.microsoft.com/beta/roleManagement/directory/roleAssignmentApprovals/xxx/steps/xxxxxx
HTTP/2.0 403 Forbidden
Vary: Accept-Encoding
Strict-Transport-Security: max-age=31536000
request-id: xxxx
client-request-id: xxxx
South","Slice":"E","Ring":"5","ScaleUnit":"006","RoleInstance":"xxx6"}}
Link: <https://developer.microsoft-tst.com/en-us/graph/changes?$filterby=beta,PrivatePreview:microsoft.applicationAuthorization&from=2025-01-01&to=2025-02-02>;rel="deprecation";type="text/html" 
{"error":{"code":"","message":"Only user tokens are supported","innerError":{"date":"2025-07-07T23:33:50","request-id":"xxx","client-request-id":"xxx"}}}
3
  • 2
    Well have you assigned the required API permissions to your service principal? Commented Jul 8 at 0:26
  • Powershell is based on Net Library. You need to set the role. Here is how it is done in c# : stackoverflow.com/questions/78663849/…. You need to do equivalent in Powershell. Commented Jul 8 at 19:33
  • Looks like application accounts are not supported, the process needs to be automated and human interaction prompt will simply not work. Any suggestions please ? It works when I run it under my personal account. Commented Jul 10 at 9:17

1 Answer 1

0

The error Only user tokens are supported means the PATCH operation for PIM approval steps requires a delegated (user) context, not an application token. In other words:

  • Interactive user flow works because Connect-MgGraph -Scopes issues a delegated token.

  • Application context fails because app-only tokens cannot perform actions that require user identity (approving PIM requests is considered a user action).

Privileged Identity Management (PIM) approval APIs enforce user-based authorization for security reasons. Approvals represent human decisions, so Microsoft Graph does not allow service principals to approve or reject requests.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.