Skip to content
This repository has been archived by the owner on Jun 30, 2023. It is now read-only.

AcquireTokenAsync(resource, clientId, userCreds) does not function in PowerShell #1130

Closed
sgiovinetti opened this issue Jul 13, 2018 · 17 comments

Comments

@sgiovinetti
Copy link

AcquireTokenAsync(resource, clientId, userCreds) throws Cannot find an overload for "AcquireTokenAsync" and the argument count: "3". in PowerShell.

The same method call works perfectly in .NET.

This is an issue only affecting ADALV3 and above. V2 works correctly.

@bgavrilMS
Copy link
Member

What version of PowerShell are you using? And of ADAL? Could you paste a code sample of how you are calling AcquireTokenAsync from PS?

@sgiovinetti
Copy link
Author

PS Version: 5.1.15063

ADAL version: tried with all the 3.X versions. All failed. Latest working is V. 2.18

@bgavrilMS
Copy link
Member

Which overload of AcquireTokenAsync are you using?

public async Task AcquireTokenAsync(
string resource,
string clientId,
UserAssertion userAssertion)

@sgiovinetti
Copy link
Author

No AcquireTokenAsync(string resource, string clientId, UserCredential userCreds)
This is the unique method for obtaining a valid token for using with PBI embedded since PBI embedded API use the "On-Behalf-Of" Oauth2 flow and not the client_credentials flow.

This overlaod method is shown and works perfectly in C# but for some reasons does not appear in PS.

@bgavrilMS
Copy link
Member

Got it, I know what the problem is. This overload of AcquireTokenAsync was moved to an extension class. I believe the reason for this was to make it less discover-able (sic) since we don't encourage using this low.

https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/blob/dev/adal/src/Microsoft.IdentityModel.Clients.ActiveDirectory/Features/WinCommon/AuthenticationContextIntegratedAuthExtensions.cs

So to invoke it from PowerShell you would use smth like:

[AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync

@bgavrilMS
Copy link
Member

@sgiovinetti
Copy link
Author

Tried this code like you suggested but result in Unable to find type [AuthenticationContextIntegratedAuthExtensions].

Could you please suggest how to modify it for let it working?

$adal = "D:\Azure\Power BI\PowerShell\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"

[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null

$ADAuthorityURL = "https://login.windows.net/common/oauth2/authorize/"   
$resourceURL = "https://analysis.windows.net/powerbi/api"

Write-Host "Retrieving the AAD Credentials...";

$credential = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential($AADuserName, $AADpassword);
$authenticationContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext($ADAuthorityURL);
$authenticationResult = [AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authenticationContext, $resourceURL, $AADClientID, $credential).Result;                    

$ResultAAD = $authenticationResult.AccessToken;

@bgavrilMS
Copy link
Member

bgavrilMS commented Jul 19, 2018

@sgiovinetti - you need to use the fully qualified name for AuthenticationContextIntegratedAuthExtensions, i.e.

$authenticationResult = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authenticationContext, $resourceURL, $AADClientID, $credential).Result;

@bgavrilMS
Copy link
Member

bgavrilMS commented Jul 19, 2018

Oh and by the way, PS 5+ does have a using namespace construct, i.e.

`
#Require -Version 5.0
using namespace Microsoft.IdentityModel.Clients.ActiveDirectory

$adalDll = [Reflection.Assembly]::LoadFile("<path_to>\Microsoft.IdentityModel.Clients.ActiveDirectory.dll")

$ADAuthorityURL = "https://login.windows.net/common/oauth2/authorize/"
$resourceURL = "https://analysis.windows.net/powerbi/api"
$AADuserName = "foo"
$AADpassword = "bar"

Write-Host "Retrieving the AAD Credentials...";

$credential = New-Object UserPasswordCredential($AADuserName, $AADpassword);
$authenticationContext = New-Object AuthenticationContext($ADAuthorityURL);
$authenticationResult = [AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authenticationContext, $resourceURL, $AADClientID, $credential).Result;

$ResultAAD = $authenticationResult.AccessToken;
`

@sgiovinetti
Copy link
Author

Great this works!
Thank you for the support.

@jmprieur
Copy link
Contributor

@bgavrilMS

This comment has been minimized.

@sgiovinetti
Copy link
Author

sgiovinetti commented Jul 19, 2018

@bgavrilMS and @jmprieur : why this flow is not recommended by MS and at the same time is the unique method for retrieving an AAD token valid for calling the Power BI generate token API for embedding a dashboard in "App owns data" scenario like is referenced here and also in this code?

@jmprieur
Copy link
Contributor

@sgiovinetti : Username/Password is not recommended for many reasons, explained in #482. In particular it is not compatible with Azure AD tenants where the administrator has enabled conditional access policies (for instance two factor authentication)

We need to work with the PowerBI people so that they change their samples to use the Onbehalf of flow or the client credentials flow.

cc: @bgavrilMS @henrik-me @jennyf19

@sgiovinetti
Copy link
Author

@jmprieur: client credentials flow does not function in PBI. I checked already in a call with MS support. You need to authenticate passing a user identity because on MS/PBI side they use to validate that you own a PBI pro license.

Maybe the Onbehalf of flow is the unique viable solution but I was not able to find any sample anywhere.

Would be great if you can provide one.

@jmprieur
Copy link
Contributor

@sgiovinetti : On-behalf-of is explained in Service to service calls on behalf of the user, and there are 2 samples (see the bottom of that page)

@sgiovinetti
Copy link
Author

sgiovinetti commented Jul 19, 2018

@jmprieur : This 2 samples imply that user login interactively. This is not the PBI scenario. Here we have an internet web app where users do not authenticate at all. The app backend needs to call the Power BI API impersonating what MS calls master user that is a unique fictitious user that owns a PBI pro license and requires the PBI dashboards/reports etc. on behalf of all the internet not authenticated users.

If there is another way please share and align with PBI product team because they say that password flow is the unique working for embedding PBI dashbaords/reports etc.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants