Easiest ways to get an access token to the Microsoft Graph

I very often work with PowerShell, needing to access the Microsoft Graph, and require an access token. Here are my favorite ways to get an access token without needing to create app registrations in Azure AD.

Method 1 – Graph Explorer

Not requiring anything installed other than a browser, simply get the access token from the Graph Explorer.

  • Go to graph.microsoft.io and click on graph explorer – or store this url
  • Click on the sign in button on the left
  • After signing in you can now access what ever you need to do directly from the Graph Explorer, or, you can click on “Access token” and extract it for being put into the authorization header

One super great feature here, given that you have the ability to consent on your organization’s behalf, is that you can modify the scopes directly on the Graph Explorer, AND it even suggests which scopes to consent to based on the url you type!

Method 2 – Azure CLI

Azure CLI contains a method az account get-access-token that returns an access token. The following is a quick example on how to get this access token – all magic happens on line 5:

# Log into Azure CLI
az login --allow-no-subscriptions

# Get access token and build $restParams that can be added using the @restParams method
$accessToken = az account get-access-token --resource-type ms-graph | ConvertFrom-Json
$restParams = @{Headers=@{Authorization="$($accessToken.tokenType) $($accessToken.accessToken)"}}

# Url to Graph
$g = "https://graph.microsoft.com"

# Example query for me endpoint
$me = Invoke-RestMethod "$g/v1.0/me" @restParams

# Get applications with displayname DemoApp1
$applications = Invoke-RestMethod "$g/v1.0/applications?`$filter=displayName eq 'DemoApp1'" @restParams

# Ensure DemoApp1 is created
if(!$applications.value){
    Write-Verbose "Creating app DemoApp1" -Verbose
    $body = @{
        displayName = "DemoApp1"
    } | ConvertTo-Json -Depth 5
    $app = Invoke-RestMethod "$g/v1.0/applications" @restParams -Body $body -Method Post -ContentType application/json
    Write-Verbose "Created with appid $($app.appid)" -Verbose
} else {
    $app = $applications.value | Select -first 1
    Write-Verbose "App already exists with appid $($app.appId)" -Verbose
}

if((Read-Host "Continue deleting app $($app.displayName)? (N/y)") -eq "y") {
    Invoke-RestMethod "$g/v1.0/applications/$($app.id)" -Method Delete @restParams
}

# Get administrative units
$AUs = Invoke-RestMethod "$g/beta/administrativeUnits" @restParams
if($AUs.value.displayName -notcontains "Test") {
    Write-Verbose "Creating AU 'Test'" -Verbose
    $body = @{
        displayName = "Test" 
    } | ConvertTo-Json -Depth 5
    $au = Invoke-RestMethod "$g/beta/administrativeUnits" @restParams -Body $body -Method Post -ContentType application/json
    Write-Verbose "Created with id $($au.id)" -Verbose
} else {
    $au = $AUs.value | select -first 1
}

A caveat for this method:

  • Only the following scopes are available, which makes some endpoints fail (such as Entitlement Management endpoints): AuditLog.Read.All Directory.AccessAsUser.All Group.ReadWrite.All User.ReadWrite.All
    • Don’t be fooled though, the Directory.AccessAsUser.All solves most problems, so you can create app registrations, service principals etc. using this method

Method 3 – Stealing it from the Azure Active Directory module

This one is a bit funky. ADAL has a token cache that can be accessed, and if you have a session with the Azure AD PowerShell Module, you can actually extract the token from the cache – given that you are in the same PowerShell session.

Connect-AzureAD

function Get-AzureADAccessTokenFromActiveSession
{
    [CmdletBinding()]
    Param()
 
    Process
    {
        # Trigger dummy request to make sure we have an access token to graph.microsoft.com
        Get-AzureADMSGroup -Top:1 | Out-Null
 
        $AadModule = Get-Command Connect-AzureAD | Select-Object -ExpandProperty Source | Get-Module
        $adal = Join-Path -Path $AadModule.ModuleBase -ChildPath 'Microsoft.IdentityModel.Clients.ActiveDirectory.dll'
        $adalforms = Join-Path -Path $AadModule.ModuleBase -ChildPath 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll'   
        [System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
        [System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
    
        $currentSession = Get-AzureADCurrentSessionInfo
        $authority = "https://login.microsoftonline.com/$($currentSession.TenantId)"
 
        $authContext = New-Object -TypeName 'Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext' -ArgumentList $authority
        $authContext.TokenCache.ReadItems() | ? Resource -eq 'https://graph.microsoft.com' | Select-Object -ExpandProperty AccessToken
    }
}

$Token = Get-AzureADAccessTokenFromActiveSession

There is a caveat here too – it does not always work, and I have no idea why..

There are of course many, many methods of getting an access token when using your own app registrations and so on, but that was not the scope of this blog post šŸ™‚ Hope this helps someone!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s