4
votes

I'm creating an Azure AD application using AzureAD module to call Microsoft Graph API. I can successfully generate the access token. But, when I try to call the API I have an error "message": "Invalid scope claims/roles.".

When I click on "Grant Permissions" button in my created application in Azure Portal and retry the call to API, the call is working.

I don't find anywhere how to do this "Grant Permissions" actions with Powershell. Is there a way to do that ?

Thanks

Damien

4
This case may be helpful to you: stackoverflow.com/questions/43143075/…Wayne Yang
Thanks @WayneYang-MSFT for the quick reply. I already added prompt="admin_consent" in authentication request body. It's not enough to "Grant Permissions".Damien Celle
You should use &prompt=admin_consent, NOT prompt="admin_consent". Also , Ensure the azure account you logged in is an admin account.Wayne Yang
Even if i use &prompt=admin_consent in REST URL, the result is still the same.Damien Celle

4 Answers

7
votes

There is an easy way to do this (as admin), it requires you have the AzureAD and AzureRM modules installed for Powershell and is not supported by Microsoft.

Original post / reference to my blog is here: http://www.lieben.nu/liebensraum/2018/04/how-to-grant-oauth2-permissions-to-an-azure-ad-application-using-powershell-unattended-silently/

The specific code sample that should help you accomplish this:

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 {$_.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
}
1
votes

I came across the same error 'Refresh token is malformed'. When reading out the refreshtoken the token was twice in the string. Resolved it by adding the line

$refreshtoken = $refreshtoken.Split("`n")[0]
0
votes

If I am not wrong, then it is using "Admin Consent". In that case, you should be using &prompt=admin_consent in the auth request directly.

If your application requests an app-only permission and a user tries to sign in to the application, an error message is displayed saying the user isn’t able to consent.

Whether or not a permission requires admin consent is determined by the developer that published the resource, and can be found in the documentation for the resource.

Link: Multi-tenant App pattern

List of Available permissions for the Azure AD Graph API and Microsoft Graph API are

Graph API Permission Scopes

Consent Framework

Hope it helps.

0
votes

This answer builds on top of Jos's answer.

Active Directory Authentication library doesn't make the refresh tokens publicly available anymore. More information can be found in github/azure-powershell/7525.

The modified snippet below worked for me

Connect-AzAccount
$context = Get-AzContext
$tenantId = $context.Tenant.TenantId
Connect-AzureAD -TenantId $tenantId -AccountId $context.Account.Id

$appId = 'Your Application ID'
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $tenantId, $null, "Never", $null, "74658136-14ec-4630-ad9b-26e160ff0fc6")
$headers = @{
    'Authorization' = 'Bearer ' + $token.AccessToken
    '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/$appId/Consent?onBehalfOfAll=true"
Invoke-RestMethod -Uri $url -Headers $headers -Method POST -ErrorAction Stop