Get Access Token by Delegated permissions using PowerShell

In this blog, we will explore how to get Access Token for Delegated permissions (On behalf of a user) for a Microsoft 365 user in PowerShell. We can acquire a token with client credentials grant flow for application permissions. For delegated permissions, we can use the MSAL.PS library to acquire a new access token with an Azure AD application.

Summary

Install MSAL.PS module

We can use the MSAL.PS library to acquire OAuth tokens for an Azure AD app with public and confidential clients. Authentication with a public client can be interactive, integrated Windows auth, or silent (aka refresh token authentication). Run the following command to install the MSAL.PS module from PowerShell Gallery.

Install-Module -Name MSAL.PS

Once you installed the module, you can use the built-in help commands in PowerShell to learn about each command in the module.

## View usage examples.
Get-Help Get-MsalToken -Examples

## View full help.
Get-Help Get-MsalToken -Full

Get Access Token by Interactive Sign-in

Run the following commands to get Access Token on behalf of a user by sending the required delegated permission Scopes as comma-separated values. The commands will prompt an interactive sign-in pop-up to complete the login process and grant consent to use the requested scope permissions.

In this example, we used the Microsoft Graph PowerShell app id. If needed, use your own Azure AD app. Refer to this post for more details about How to Register and Configure Azure AD application.

#Provide your Office 365 Tenant Domain Name or Tenant Id
$TenantId = "contoso.onmicrosoft.com"
#$TenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  
#Used the Microsoft Graph PowerShell app id. You can create and use your own Azure AD App id if needed.
$AppClientId="14d82eec-204b-4c2f-b7e8-296a70dab67e"
  
$MsalParams = @{
   ClientId = $AppClientId
   TenantId = $TenantId
   Scopes   = 'https://graph.microsoft.com/User.Read.All','https://graph.microsoft.com/Files.Read.All'
}
 
$MsalResponse = Get-MsalToken @MsalParams
$AccessToken  = $MsalResponse.AccessToken

#Display the token in the PS console
$AccessToken

Get Access Token by User credentials without user interaction

Sometimes, we may need to get access token without user interaction (without a login-prompt window) by passing the required user credentials. We can also use the MSAL.PS library for unattended sign-in access using ROPC flow.

Run the following PowerShell commands to get an OAuth token on behalf of a user by providing the required user credentials (username and password).

#Provide your Office 365 Tenant Domain Name or Tenant Id
$TenantId = "contoso.onmicrosoft.com"
#$TenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  
#Used the Microsoft Graph PowerShell app id. You can create and use your own Azure AD App id if needed.
$AppClientId="14d82eec-204b-4c2f-b7e8-296a70dab67e"
  
$MsalParams = @{
   ClientId = $AppClientId
   TenantId = $TenantId
   Scopes   = 'https://graph.microsoft.com/User.Read.All','https://graph.microsoft.com/Files.Read.All'
}

#Specify user credentials
$username = "[email protected]"
$password = "user_password"
$securePwd = ConvertTo-SecureString $password -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ($username, $securePwd)

#If required, use Get-Credential cmdlet to get user credentials
#$Cred = Get-Credential

#Acquire token by passing user credentials  
$MsalResponse = Get-MsalToken @MsalParams -UserCredential $Cred
$AccessToken  = $MsalResponse.AccessToken
 
#Display the token in the PS console
$AccessToken

Note: The required user consent (or Admin consent) should have been already granted for the requested Delegated permission scopes. If the required consent is not provided, you will get the following error message.

Get-MsalToken : AADSTS65001: The user or administrator has not consented to use the application with ID ’14d82eec-204b-4c2f-b7e8-296a70dab67e’ named ‘Microsoft Graph PowerShell’. Send an interactive authorization request for this user and resource.

To provide the required consent, you need to use the above Interactive login method (one time alone) and then use this method. If the permission requires Admin consent, then the consent should have been provided by the Global administrator account to use the permission for all users (Consent on behalf of your organization), so that normal users can use the app to obtain the token.

Use the Access Token to call Microsoft Graph API

Once you obtained the required Access Token, use the Invoke-RestMethod cmdlet to call the Rest API with the access token. The below commands call the list users endpoint in the Microsoft Graph API resource and retrieve details of Azure AD users.

#Provide your access token 
#$AccessToken="eyJ0eXAiOiJ......" 
  
#Form request headers with the acquired $AccessToken
$headers = @{'Content-Type'="application\json";'Authorization'="Bearer $AccessToken"}
  
#This request gets all users list
$ApiUrl = "https://graph.microsoft.com/v1.0/users"
 
$Response = Invoke-RestMethod -Method GET -Uri $ApiUrl -ContentType "application\json" -Headers $headers
$Users = $Response.value
Advertisement

3 thoughts on “Get Access Token by Delegated permissions using PowerShell”

  1. Hello Morgan,

    nice blog entry – and give a good insight. But, is it also possible to goon with certificate and certificate auth, if such is stored to the app registration? So, i don’t have a client secret, and was using the “-CertificateThumbprint” in the oldest Team Module 1.1.6…

    Do you know, if this is also possible right know?

    Reply
    • Yes, this is possible. But I have not tried it personally. Can you try the below commands?

      $ClientCertificate = Get-Item Cert:\CurrentUser\My\0000000000000000000000000000000000000000
      $MsalClientApplication = Get-MsalClientApplication -ClientId '00000000-0000-0000-0000-000000000000' -ClientCertificate $ClientCertificate -TenantId '00000000-0000-0000-0000-000000000000'
      $MsalResponse = $MsalClientApplication | Get-MsalToken -Scope 'https://graph.microsoft.com/.default'
      $AccessToken = $MsalResponse.AccessToken

      Reply
  2. I’m trying to use the “Get Access Token by Interactive Sign-in” method but I’m getting the error “Get-MsalToken : AADSTS650053: The application ‘Microsoft Graph Command Line Tools’ asked for scope ‘PrivilegedAccess.PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup’ that doesn’t exist on the resource ‘00000003-0000-0000-c000-000000000000′”.

    The account I’m interactively signed-in with that is running Get-msalToken has a user consent in the MS Graph Powershell enterprise application for the permission/scope I need (in this case PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup) and your article would suggest that’s enough, but it seems the enterprise application needs to have an admin consent for that permission/scope in order to retrieve the token on my behalf.

    I can’t work out a way to add that admin consent to the enterprise application without first removing all my user consents and asking for them again but this time with “for all users”.

    Reply

Leave a Comment