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

PowerShell MCP Azure Function Server

Recently under the experimental Azure Functions build Microsoft Developer Advocates have shown enabling Azure Functions…

2 weeks ago

EntraPulse – Your AI-Powered Gateway to Microsoft Graph & Docs

Today, I’m super excited to finally announce the Beta release of EntraPulse Lite – a…

2 months ago

Lokka MCP Authentication Enhancements

I'm excited to share some significant authentication enhancements I've contributed to the Lokka MCP Server…

3 months ago

AI Inception: Building AI Solutions with AI for AI

Last month I had the pleasure of speaking at the Sydney event for Global Azure.…

4 months ago

A Have I Been Pwned MCP Server for Claude

Model Context Protocol (MCP) is a powerful framework that extends AI clients like Claude and…

6 months ago

Azure AI Developer Hackathon

I've just completed participating in the Azure AI Developer Hackathon that was looking to provide…

6 months ago

This website uses cookies.