UPDATE (2018-02-12): The method described below does not work, unfortunately. Connect-AzureAD
runs without error but the AD context you get is not authorized to perform AD operations. I get errors that look like this:
Get-AzureADApplication : Error occurred while executing GetApplications
Code: Authentication_MissingOrMalformed
Message: Access Token missing or malformed.
RequestId: 1f15adc8-1cf5-443b-b78d-88db66701506
DateTimeStamp: Mon, 12 Feb 2018 16:43:42 GMT
HttpStatusCode: Unauthorized
HttpStatusDescription: Unauthorized
HttpResponseStatus: Completed
The access token is missing or malformed. I'm trying to figure out what goes wrong since an access token is actually provided (so it can not be missing). But 'malformed' is also strange because this is the token I get back from Add-AzureRmAccount
.
Checking the actual access token in jwt.io proves that is isn't malformed. However, the token audience is https://management.core.windows.net/
. This is probably not the audience that is expected when authenticating against Azure AD (unfortunately we can not inspect this token). So that is probably why the token is 'malformed'.
This means I'm stuck with a double login when using both Add-AzureRmAccount
and Connect-AzureAD
in one PowerShell script... If someone knows a solution, please leave a comment :)
UPDATE (2018-02-13): I also found out that it doesn't really matter what you pass as access token to Connect-AzureAD
. The following runs without error: Connect-AzureAD -TenantId $tenantId -AadAccessToken "this is no token" -AccountId $accountId
. Errors happen only later when you try to run operations against Azure AD.
I had to write a PowerShell script that connected to Azure Resource Manager via Add-AzureRmAccount
and to Azure AD via Connect-AzureAD
. If you write your script like this:
Add-AzureRmAccount -SubscriptionId $subscriptionId
Connect-AzureAD -TenantId $tenantId
you are presented twice with this login dialog:
This is of course annoying for users of my script so I set out to improve this. The end result looks like this:
$rmAccount = Add-AzureRmAccount -SubscriptionId $subscriptionId
$tenantId = (Get-AzureRmSubscription -SubscriptionId $subscriptionId).TenantId
$tokenCache = $rmAccount.Context.TokenCache
$cachedTokens = $tokenCache.ReadItems() `
| where { $_.TenantId -eq $tenantId } `
| Sort-Object -Property ExpiresOn -Descending
Connect-AzureAD -TenantId $tenantId `
-AadAccessToken $cachedTokens[0].AccessToken `
-AccountId $rmAccount.Context.Account.Id
Let's dissect this:
- Login to Azure Resource Manager and store the result.
- Get the tenant id from the subscription.
- Get the token cache property from the ARM account. This is an object of type
Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache
from the ADAL library. - We can retrieve the access token we want through the
ReadItems()
method, filtering on tenant id and getting the most recent one. - And finally we can use the access token to connect to Azure AD.
And that's how we prevent a double login in PowerShell scripts that use both Add-AzureRmAccount
and Connect-AzureAD
.