Using pipeline identity for Connect-AzureAD, Graph and other endpoints

Azure Pipelines and Azure Functions (and Automation Accounts) can have managed identities, in other words, a service principal. This service principal can be assigned to Azure AD roles (e.g. to modify users / devices) or graph / Azure RM resources. A service principal could even be a global admin, and Service Principals don’t have to do MFA…. 🙂

In both Pipelines and Functions the new Az module is enabled and logged into your tenant by default as the service principal, how cool would it be to use that identity to do those (hopefully few) things that are still only supported by e.g. the AzureAD module?

Here’s an example on getting tokens for Azure AD and for Graph, obviously you could also get tokens for other audiences the same way:

$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "").AccessToken
$aadToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "").AccessToken

Write-Output "Hi I'm $($context.Account.Id)"

Connect-AzureAD -AadAccessToken $aadToken -AccountId $context.Account.Id -TenantId $

get-azureaduser -Top 5

If you want to do this from an old fashioned Azure Runbook (please move to functions!) then you’ll have to log in to Az first:

    $servicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
    Connect-AzAccount -Tenant $servicePrincipalConnection.TenantID `
        -ApplicationId $servicePrincipalConnection.ApplicationID   `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint `
}catch {
    Write-Error -Message $_.Exception
    throw $_.Exception

Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Ivan Ignatiev
3 years ago

Hi Jos,

It seems you have forgot the parameter:

-MsAccessToken $graphToken

in your


to fully authenticate in AzureAD

some command does not work without this

3 years ago

Thank you for providing this info. Works pretty well. What I’m trying to achieve is, connecting to ExchangeOnline with a Bearer-Token. The thing is, there’s a token generated by my second commandline. But then, with the command New-PSSession I get the message, I’m not authorized. If I catch with Fiddler the token generated by the command Connect-ExchangeOnline and insert it into $exoToken, I can connect with the following code. Any idea how I make this code work? $context = Get-AzContext # Build the auth information $exoToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "").AccessToken $Authorization = "Bearer {0}" -f $exoToken… Read more »

2 years ago

Hi Jos,

Thanks for this post.

I’ve been trying to use this to login to graph and do some Intune automation but when I see the tokens that are generated I don’t get anything from DeviceManagementManagedDevices permissions

Is there a way to point to an ApplicationID on this process or anything that can help me authenticate with Delegated permissions without creating App Secrets?

2 years ago

Hi. Thanks for your approach with example script.
I am trying to apply the same concept in order to apply it on Connect-MsolService, so it should be something like the script below,

$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, “”).AccessToken
$aadToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, “”).AccessToken
Write-Output “Hi I’m $($context.Account.Id)

Connect-MsolService -AdGraphAccessToken $aadToken -MsGraphAccessToken $graphToken

However, I got the error: Connect-MsolService: IDX10703: Unable to decode the ‘header’: ‘eyJ0e….<the jwt token>’.

Have everyone tried to Connect-MsolService in this way?
Anny idea how to make this work?

Thanks a million, any help appreciated.

3 years ago

Hi Jos,

Thank you for this!
This appears to work for almost all the AzureAD cmdlets but today I stumbled across one that didn’t work.


Would you have any idea on why this command would not work using the above authentication approach?
Any thoughts on this would be appreciated.

The error I’m getting is Object reference not set to an instance of an object.

Last edited 3 years ago by frasier
4 years ago

Hi Jos, I am following the same process did the following : created the SPN Added the Graph Permissions for create Group and Group readwrite Acquired the token also during the process. When it tried to connect it throws out the error. ]Error occurred while executing GetUsers Code: Authorization_RequestDenied Message: Insufficient privileges to complete the operation. Permissions on Graph: Group.Create Group.Read.All User.Read Application.ReadWrite.Owned Directory.Read.All all are admin consent for the tenant Any advice would be great as i can run the same script from the local it works.From the pipeline it throws the Error as i did created the SPN access on subscription to “Contributor” also. The SPN is set manually… Read more »

Last edited 4 years ago by Vishnu