Search code examples
azurepowershellazure-active-directory

Get a valid token with Invoke-WebRequest and use with application


Expose APIAPI PermissionsI am using PowerShell to get a token, there are 2 ways to get the token, when I supply the following parameters: UserName, password, ClientID, Client Secret

$response = Invoke-WebRequest -Uri "https://login.microsoftonline.com/TentantID/oauth2/v2.0/token" -Method Post -Body @{
    grant_type = "password"
    client_id = ""
    username = ""
    password = ""
    client_secret = ""
    scope = 'openid offline_access https://xxxx.onmicrosoft.com/xxxxx/user_impersonation'
}
$token = (ConvertFrom-Json $response.Content).access_token

For this token I can work and make actions

When I am using this script and also get a token but I don't have permissions:

$response = Invoke-WebRequest -Uri "https://login.microsoftonline.com/TenantID/oauth2/v2.0/token" -Method Post -Body @{
    grant_type = "client_credentials"
    client_id = ""
    client_secret = ""
    scope = 'openid offline_access https://xxxx.onmicrosoft.com/xxxxx/.default'
}
$token = (ConvertFrom-Json $response.Content).access_token

I added the following permission to the right application (under API permissions) Directory.Read.All and Group.Read.All There are more rows with type delegated (I added the same rows to type application)

Regarding the Expose an API section, there is only one row:

https://xxxx.onmicrosoft.com/xxxxx/user_impersonation

What am I missing? I want to work without to insert user and password !!!


Solution

  • Get a valid token with Invoke-WebRequest and use with application

    You cannot get delegated permissions in token generated with client credentials flow. To get application permissions in token and read the user information, change scope to graph.microsoft.com/.default

    If you're using a customized API to read the information, username and password or authorization code flow is the only available options.

    Here is the PowerShell code to read the user information using client credentials by using Microsoft Graph.

    $response = Invoke-WebRequest -Uri "https://login.microsoftonline.com/226cf998-ddcc-4005-acfb-9bbfa7d40283/oauth2/v2.0/token" -Method Post -Body @{
        grant_type = "client_credentials"
        client_id = ""
        client_secret = ""
        scope = 'https://graph.microsoft.com/.default'
    }
    $token = (ConvertFrom-Json $response.Content).access_token
    
    $graphApiUrl = "https://graph.microsoft.com/v1.0/users"
    
    $usersResponse = Invoke-RestMethod -Uri $graphApiUrl -Headers @{
        Authorization = "Bearer $token"
    }
    $usersResponse.value | ForEach-Object {
        Write-Host "User Display Name: $($_.displayName)"
        Write-Host "User Principal Name: $($_.userPrincipalName)"
        Write-Host "----------"
    }
    

    Response:

    enter image description here

    Token response in JWT.ms

    enter image description here