Interactive Authentication to Microsoft Graph using MSAL with PowerShell and Delegated Permissions

Previously I’ve written about using MSAL and PowerShell with Application Permissions and Client Credentials and Certificate based authentication. Also with Delegated Permissions and Device Code flow authentication. The one I haven’t written a post on is performing interactive authentication to Microsoft Graph using MSAL with PowerShell and Delegated Permissions. I have for Python so this post will complete the examples for both Python and PowerShell.

The details in this post have been successfully validated with both PowerShell and Windows PowerShell.

Delegated permissions in Azure AD requires authorization from the consumer of the registered Azure AD Application versus Application permissions assigned to a registered Azure AD Application. I’ve covered a lot of using Delegated Permissions with registered Azure AD Applications in the links in the opening paragraph. So in this post I’m going to show using Delegated Permissions via a well-known Azure AD registered Application. In this post I listed a bunch of the well-known AAD registered applications. I’ll be using the Azure PowerShell Client ID “1950a258-227b-4e31-a9cf-717495945fc2” with the delegated permission “user_impersonation“.

MSAL with PowerShell and Delegated Permissions

Here then is the quick start guide to again using the fantastic MSAL.PS PowerShell module. It simplifies the process of obtaining and refreshing access and refresh tokens. Since my previous posts on using MSAL.PS, the module has been updated numerous times to keep current with releases of the MSAL Authentication Libraries.

If you aren’t already using it, install it from the PowerShell Gallery from an administrative PowerShell session:

Install-Module -name MSAL.PS -Force -AcceptLicense

Obtaining an Access Token

As I mentioned earlier in this example we are going to use the Azure PowerShell registered application with delegated permissions as ourselves (our Azure AD User account). That along with our Tenant name and MSAL.PS will allow us to initiate an interactive authentication flow and receive an Access Token for our API calls.

NOTE: This part of the process is only required once to receive the initial Access and Refresh Token. We can silently refresh our tokens after the first interactive authentication.  

Import-Module MSAL.PS

$resource = "https://graph.microsoft.com" # Microsoft Graph
$scope = "user_impersonation" # Delegated User Impersonation
$clientID = "1950a258-227b-4e31-a9cf-717495945fc2" # Azure PowerShell
$tenantID = "idmspecialist.com" # AAD Tenant Name
$myUPN = "darrenjrobinson@idmspecialist.com" # User UPN

$myAccessToken = Get-MsalToken -ClientId $clientID `
        -TenantId $tenantID `
        -Scopes "$($resource)/$($scope)" `
        -LoginHint $myUPN 

Running the above (updated for your registered AAD Tenant Name and your Azure AD User UPN will trigger Windows to show the Account Selector dialog window as shown below. Your identity should be listed. Select it and authenticate.

Using my JWTDetails PowerShell Module we can investigate the Access Token we just received. We can see that it was issued against the Microsoft Azure PowerShell App with the user_impersonation scope

Import-Module JWTDetails
$myAccessToken.AccessToken | Get-JWTDetails

Obtaining a new Access Token using the Refresh Token

The MSAL.NET library which the MSAL.PS Module leverages (via Microsoft.Identity.Client.dll) doesn’t reveal the Refresh Token. If you look at $myAccessToken you will see the Access Token and IdToken but no RefreshToken.

However, whilst you can’t see the Refresh Token the MSAL cache has the refresh token, and it can be used by MSAL.PS to SILENTLY obtain a new Access Token. And the MSAL.PS Module handles that for you, if you use the following options to obtain a new Access Token:

$myAccessToken = Get-MsalToken -ClientId $clientID -TenantId $tenantId -Silent

You will notice we didn’t get prompted with the identity selector as the use of -silent and our cached refresh token allowed MSAL.PS to refresh our tokens. If you want to force a refresh of the tokens you can also use the -ForceRefresh option.

$myAccessToken = Get-MsalToken -ClientId $clientID -TenantId $tenantId -Silent -ForceRefresh

Using the Access Token

We can simply use our Access Token in the header of an Invoke-RestMethod request to the Microsoft Graph API as shown below to query our Azure AD User object.

# Get User Object via AAD Graph
$myUserObj = Invoke-RestMethod -Method Get `
    -Uri "$($resource)/beta/users/$($myUPN)" `
    -Headers @{Authorization = "Bearer $($myAccessToken.AccessToken)" }

The screenshot below shows the query and the returned user object as returned from the Microsoft Graph API.

Summary

Using the MSAL.PS PowerShell Module we can quickly obtain an Azure AD Access Token with Delegated Permissions using interactive authentication, and then silently refresh our Access Token leveraging the MSAL.PS Module, the MSAL.NET library and the token cache.

I you want to query Microsoft Graph for information other than what can be returned using your identity and base level user impersonation permissions you will need to register an Azure AD Application with the delegated permissions for your requirements and simply update the $clientID variable.