How to grant OAuth2 permissions to an Azure AD Application using PowerShell unattended / silently

You may know this button:There is no native Powershell command to grant OAuth permissions to an Azure AD Application, so I wrote a function for that. Note that this is NOT a supported way to grant permissions to an application because it does not follow the proper admin consent flow that applications normally use.

The great advantage of my method is that it can be used to grant permissions silently, AND to ‘hidden’ and/or multi-tenant applications that companies like Microsoft use for backend stuff like the Intune API. (e.g. the ‘Microsoft Intune Powershell’ multi-tenant application).

The function requires AzureAD and AzureRM modules installed!


Function Grant-OAuth2PermissionsToApp{
    Param(
        [Parameter(Mandatory=$true)]$Username, #global administrator username
        [Parameter(Mandatory=$true)]$Password, #global administrator password
        [Parameter(Mandatory=$true)]$azureAppId #application ID of the azure application you wish to admin-consent to
    )

    $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
    $mycreds = New-Object System.Management.Automation.PSCredential ($Username, $secpasswd)
    $res = login-azurermaccount -Credential $mycreds
    $context = Get-AzureRmContext
    $tenantId = $context.Tenant.Id
    $refreshToken = @($context.TokenCache.ReadItems() | Where-Object {$_.tenantId -eq $tenantId -and $_.ExpiresOn -gt (Get-Date)})[0].RefreshToken
    $body = "grant_type=refresh_token&refresh_token=$($refreshToken)&resource=74658136-14ec-4630-ad9b-26e160ff0fc6"
    $apiToken = Invoke-RestMethod "https://login.windows.net/$tenantId/oauth2/token" -Method POST -Body $body -ContentType 'application/x-www-form-urlencoded'
    $header = @{
    'Authorization' = 'Bearer ' + $apiToken.access_token
    'X-Requested-With'= 'XMLHttpRequest'
    'x-ms-client-request-id'= [guid]::NewGuid()
    'x-ms-correlation-id' = [guid]::NewGuid()}
    $url = "https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$azureAppId/Consent?onBehalfOfAll=true"
    Invoke-RestMethod –Uri $url –Headers $header –Method POST -ErrorAction Stop
}

GITLAB: Grant-OAuth2PermissionsToApp.ps1

Update 2021: improved / mfa compatible token function

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

13 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Alexander
Alexander
3 years ago

It seems that in powershell we can invoke the Azure CLI. I am able to grant permission like this

az ad app permission grant –id $appId –api $apiAppId –scope $scope

Arturo
Arturo
4 years ago

Does this still work? I get the token for this resource but when I invoke the call Consent I receive the follwing error: AADSTS700027: Client assertion contains an invalid signature.
[Reason – The key was not found., Thumbprint of key used by client: ‘D7F5A38DC17A321291F8DC71D11676C9543B9F84’, Please visit ‘https://developer.microsoft.com/en-us/graph/graph-explorer’ and query for ‘https://graph.microsoft.com/beta/applications/74658136-14ec-4630-ad9b-26e160ff0fc6’ to see
configured keys]

Audun
Audun
4 years ago

Hey and thanks for a good article,

I’m trying to use your example to automate giving consent to get a multi tenant SP in tenant B into tenant A. I log in with global admin and do the rest call you describe, without much success =) Is the IAM api you use equivalent to what is used here :

https:// login.microsoftonline.com/TENANT2_ID/oauth2/authorize?client_id=CLIENT_ID_OF_MULTI_TENATED_APPLICATION&response_type=code&redirect_uri=http%3A%2F%2Fwww.microsoft.com%2F

This is the only way I’ve managed to connect the SP between tenants and your post is the closest thing to a solution I’ve seen.

Hope you can help! =)

Br

Audun Ellefsen

Nima Gharib
Nima Gharib
4 years ago

Hey Jos,

Seems Microsoft has removed the ability to get the refreshtoken?
https://github.com/Azure/azure-powershell/issues/7525

Johan Maes
Johan Maes
5 years ago

This used to work but now I get the following error:
System.Net.WebException: The remote server returned an error: (400) Bad Request.
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()

trackback

[…] using Fiddler, we can see that there is a ‘hidden’ API we can use, for example, to set permissions. I’ve written a ‘clean’ function to retrieve this token silently that you can use […]