Identity and Access Management

Microsoft Graph using MSAL with PowerShell and Delegated Permissions

In October last year I authored this post that provided a getting started guide to using MSAL with PowerShell. That post also hinted at future posts expanding on additional functionality. Finally, I’m delivering on that with this post that will dive into using MSAL with PowerShell and delegated permissions. See this post for using MSAL with PowerShell and Certificate base authentication. Most recently I’ve also primarily been using PowerShell (7.x) over the earlier PowerShell Desktop (5.x) / Windows PowerShell version. 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. Delegated permissions are often required when an application is acting on behalf of a user or as in the case that prompted this blog post, a specific Graph API only supports delegated permissions.

The particular API in question (as of 8 July 2020) is the Beta version of the Azure AD Authentication Methods API. What that documentation link doesn’t say, is that the Authentication Methods API only supports Delegated Permissions. With some digging that can be found in the GitHub Repo version of the documentation here. Why is this confusing? Because on the Registered Apps Blade in Azure AD you have the option to assign Application level permissions for the Authentication Methods API as shown in the screenshot below. The option is presented, but not currently implemented.

Keep in mind this API is currently Beta and hopefully by the time you’re reading this later in 2020+ App level permissions will be available, and the API will be out of Beta.

MSAL with PowerShell and Delegated Permissions

Here then is the quick start guide to again using the fantastic MSAL.PS PowerShell module against an Azure AD Registered Application configured with Delegated Permissions. Since my previous post 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

From your Azure AD Registered Application that contains Delegated Permissions to which you have Admin Consented (if you are using it on tenant wide resources),  record your TenantID and AppID. Using those with MSAL.PS we can initiate a Device Code Authentication Flow and receive an Access Token for our API calls.

The following example with your substituted ClientID and TenantID (and assuming your registered app has a reply URL configured of https://localhost) will prompt you to navigate to https://microsoft.com/devicelogin

NOTE: This part of the process is only required once in order to authorize delegated access to the Registered App and receive the initial Access Token. 

Import-Module MSAL.PS
$clientID = "myClientID"
$tenantID = "myTenantID"
$myAccessToken = Get-MsalToken -DeviceCode -ClientId $clientID -TenantId $tenantID -RedirectUri "https://localhost"

Enter the code provided with the URL link

Provide your Username and Password and MFA (if required)  and your JWT Token will be returned to the $myAccessToken variable.

Using my JWTDetails PowerShell Module we can investigate the Access Token.

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 -RedirectUri "https://localhost"

You will notice we don’t need to use the DeviceCode flow now and we can replace it with ‘-Silent’. The Access Token will only be refreshed if it is close to expiry.

If you want to force a refresh to obtain a new Access Token use the ‘-ForceRefresh’ option:

$myAccessToken = Get-MsalToken -ClientId $clientID -TenantId $tenantId -Silent -RedirectUri "https://localhost" -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 the Authentication Methods for the current authorized user.

$myAuthMethods = (Invoke-RestMethod -Headers @{Authorization = "Bearer $($myAccessToken.AccessToken)" } `
   -Uri "https://graph.microsoft.com/beta/me/authentication/methods" `
   -Method Get).value
$myAuthMethods

The screenshot below shows the query and the returned user Authentication Methods 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 the Interactive Device Code flow, and then silently refresh our Access Token leveraging the MSAL.PS Module, the MSAL.NET library and the token cache.

Darren Robinson

Bespoke learnings from a Microsoft Identity and Access Management Architect using lots of Microsoft Identity Manager, Azure Active Directory, PowerShell, SailPoint IdentityNow and Lithnet products and services.

View Comments

Recent Posts

Visualising your IP Address using PowerShell and AI

A few weeks back the Microsoft AI Tour was in Sydney Australia. There was a…

3 weeks ago

Where the heck is the PowerShell Module loading from?

If you're anything like me you always have PowerShell open, and often both PowerShell and…

4 months ago

Express Verified ID Setup

Decentralised Identity is a technology I'm passionate about and have written many posts and tools…

5 months ago

Orchestrating 1Password with PowerShell

Over two years ago I authored a PowerShell Module that enabled the automation of 1Password.…

8 months ago

Entra ID Tenant ID & Custom Domains PowerShell Module

Buried in my PowerShell Snippets Vol 4 post from 2021 is the PowerShell script and…

8 months ago

Windows Subsystem for Linux instance has terminated

Short post on how to recovery from "The Windows Subsystem for Linux instance has terminated"…

9 months ago

This website uses cookies.