With the impending retirement of the Azure AD Graph API and ADAL authentication methods, and by impending, I mean the end of 2022, we should probably look at how we move away from the existing authentication methods I’ve been using in all of my scripts and into the new realms of MSAL (Microsoft Authentication Library).
Hold tight, this will be quick.
Background #
The driver for this move away from the now deemed legacy ADAL (Azure Active Directory Authentication Library) authentication method, is Microsoft’s aim to move everyone and everything to PowerShell 7 core and allow for full cross-platform compatibility for PowerShell.
The issue with PowerShell 7 however, is that it doesn’t natively support the ‘old’ ADAL authentication libraries only with the use of -UseWindowsPowerShell
compatibility flag, hence the need to move to an alternative authentication method.
MSAL PowerShell Module #
Save reinventing the wheel, we can use the MSAL.PS module written by Jason Thompson to achieve authentication to Graph API without the reliance on PowerShell 5 and the AzureAD or ADAL PowerShell modules.
This module has been designed to utilise PowerShell core and subsequently be operating system agnostic, with a new device code authentication workflow for devices that have constraints around input.
Install-Module MSAL.PS -Scope CurrentUser
So we can now use the well used Microsoft Intune PowerShell App Id, and our tenant information to authenticate using the MSAL.PS module using ths new -DeviceCode
option for authentication, generating a code that we can use on any device to authenticate on behalf of our initial request:
Get-MsalToken -ClientId 'd1ddf0e4-d672-4dae-b554-9d5bdfd93547' -TenantId 'ennbee.uk' -DeviceCode
-
Opening up the presented URL
https://microsoft.com/devicelogin
prompts us to enter in the code we received: -
From here we can sign in with the required User Account:
-
Confirm the Application we are signing into:
-
Finally receiving confirmation of the sign in and a prompt to close the window:
Once the Window is closed, we now have an authentication token in the shell to use to our heart’s content.
The New World #
With a new way to acquire our Graph API token, we should look at updating the tried and tested Authentication Methods kindly provided by Microsoft in the powershell-intune-samples repo that we have been relying on to authenticate to Graph API.
An Updated Function #
We need to update the Get-AuthToken
function, and sensibly rename it, to do the following:
- Detect the new MSAL.PS PowerShell module and prompt if it’s not installed
- Import the MSAL.PS PowerShell module
- Strip out the unneeded variables
- Remove any and all reference to the ADAL DLL libraries
- Get a new authentication token
Function Get-AuthTokenMSAL {
<#
.SYNOPSIS
This function is used to authenticate with the Graph API REST interface
.DESCRIPTION
The function authenticate with the Graph API Interface with the tenant name
.EXAMPLE
Get-AuthTokenMSAL
Authenticates you with the Graph API interface using MSAL.PS module
.NOTES
NAME: Get-AuthTokenMSAL
#>
[cmdletbinding()]
param
(
[Parameter(Mandatory = $true)]
$User
)
$userUpn = New-Object 'System.Net.Mail.MailAddress' -ArgumentList $User
if ($userUpn.Host -like '*onmicrosoft.com*') {
$tenant = Read-Host -Prompt 'Please specify your Tenant name i.e. company.com'
Write-Host
}
else {
$tenant = $userUpn.Host
}
Write-Host 'Checking for MSAL.PS module...'
$MSALModule = Get-Module -Name 'MSAL.PS' -ListAvailable
if ($null -eq $MSALModule) {
Write-Host
Write-Host 'MSAL.PS Powershell module not installed...' -f Red
Write-Host "Install by running 'Install-Module MSAL.PS -Scope CurrentUser' from an elevated PowerShell prompt" -f Yellow
Write-Host "Script can't continue..." -f Red
Write-Host
exit
}
if ($MSALModule.count -gt 1) {
$Latest_Version = ($MSALModule | Select-Object version | Sort-Object)[-1]
$MSALModule = $MSALModule | Where-Object { $_.version -eq $Latest_Version.version }
# Checking if there are multiple versions of the same module found
if ($MSALModule.count -gt 1) {
$MSALModule = $MSALModule | Select-Object -Unique
}
}
$ClientId = 'd1ddf0e4-d672-4dae-b554-9d5bdfd93547'
$RedirectUri = 'urn:ietf:wg:oauth:2.0:oob'
$Authority = "https://login.microsoftonline.com/$Tenant"
try {
Import-Module $MSALModule.Name
if ($PSVersionTable.PSVersion.Major -ne 7) {
$authResult = Get-MsalToken -ClientId $ClientId -Interactive -RedirectUri $RedirectUri -Authority $Authority
}
else {
$authResult = Get-MsalToken -ClientId $ClientId -Interactive -RedirectUri $RedirectUri -Authority $Authority -DeviceCode
}
# If the accesstoken is valid then create the authentication header
if ($authResult.AccessToken) {
# Creating header for Authorization token
$authHeader = @{
'Content-Type' = 'application/json'
'Authorization' = 'Bearer ' + $authResult.AccessToken
'ExpiresOn' = $authResult.ExpiresOn
}
return $authHeader
}
else {
Write-Host
Write-Host 'Authorization Access Token is null, please re-run authentication...' -ForegroundColor Red
Write-Host
break
}
}
catch {
Write-Host $_.Exception.Message -f Red
Write-Host $_.Exception.ItemName -f Red
Write-Host
break
}
}
Updating Authentication Method #
With the new Get-AuthTokenMSAL
function in our arsenal, we can quickly update the authentication method to call this function.
if ($global:authToken) {
$DateTime = (Get-Date).ToUniversalTime()
$TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes
if ($TokenExpires -le 0) {
Write-Host 'Authentication Token expired' $TokenExpires 'minutes ago' -ForegroundColor Yellow
if ($null -eq $User -or $User -eq '') {
$User = Read-Host -Prompt 'Please specify your user principal name for Azure Authentication'
}
$global:authToken = Get-AuthTokenMSAL -User $User
Write-Host 'Connected to Graph API' -ForegroundColor Green
}
Else {
Write-Host 'Connected to Graph API' -ForegroundColor Green
}
}
else {
if ($null -eq $User -or $User -eq '') {
$User = Read-Host -Prompt 'Please specify your user principal name for Azure Authentication'
}
$global:authToken = Get-AuthTokenMSAL -User $User
Write-Host 'Connected to Graph API' -ForegroundColor Green
}
Running both the function and authentication code gives us something like the below:
And once you’ve run through the Device Code authentication method show earlier, it will give you the token you need in the $authToken
variable to use across all the existing scripts in the powershell-intune-samples
Summary #
With the MSAL based authentication in place, and updating scripts to use the new function and associated code, we can lean back and relax a little when Microsoft depreciates and ends the use of ADAL based authentication methods.
If you’d like a more detailed understanding of MSAL and how to move away from ADAL, I’d recommend having a glance over the following:
- Overview of the Microsoft Authentication Library (MSAL)
- Migrate applications to the Microsoft Authentication Library (MSAL)
I won’t be, I’ll be tirelessly updating all my scripts to use the new authentication method. This is what happens when Microsoft extends their deadlines and gives you more time to use old technologies.