AzureAD / azure-activedirectory-library-for-dotnet

ADAL authentication libraries for .net
http://aka.ms/aaddev
MIT License
358 stars 214 forks source link

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

Closed sgiovinetti closed 6 years ago

sgiovinetti commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

PS Version: 5.1.15063

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

bgavrilMS commented 6 years ago

Which overload of AcquireTokenAsync are you using?

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

sgiovinetti commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

https://powershellstation.com/2017/10/06/calling-extension-method-in-powershell/

sgiovinetti commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

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("\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 commented 6 years ago

Great this works! Thank you for the support.

jmprieur commented 6 years ago

@bgavrilMS FYI, I've added a small paragraph in the conceptual documentation: https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/wiki/Acquiring-tokens-with-username-and-password#using-the-usernamepassword-flow-from-powershell

bgavrilMS commented 6 years ago

Nice, keeping the document alive 😊

From: Jean-Marc Prieur notifications@github.com Sent: Thursday, July 19, 2018 12:55 PM To: AzureAD/azure-activedirectory-library-for-dotnet azure-activedirectory-library-for-dotnet@noreply.github.com Cc: Bogdan Gavril Bogdan.Gavril@microsoft.com; Mention mention@noreply.github.com Subject: Re: [AzureAD/azure-activedirectory-library-for-dotnet] AcquireTokenAsync(resource, clientId, userCreds) does not function in PowerShell (#1130)

@bgavrilMShttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FbgavrilMS&data=02%7C01%7CBogdan.Gavril%40microsoft.com%7C210935162869487d323008d5ed6e7ddf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636675981171085967&sdata=63T2lKEDkTGVdfHc2PHvMbH8vY7Jp14xQklnYSil470%3D&reserved=0 FYI, I've added a small paragraph in the conceptual documentation: https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/wiki/Acquiring-tokens-with-username-and-password#using-the-usernamepassword-flow-from-powershellhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAzureAD%2Fazure-activedirectory-library-for-dotnet%2Fwiki%2FAcquiring-tokens-with-username-and-password%23using-the-usernamepassword-flow-from-powershell&data=02%7C01%7CBogdan.Gavril%40microsoft.com%7C210935162869487d323008d5ed6e7ddf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636675981171095971&sdata=Pqi4%2B%2B6MKVGk9U7iZb7jspB3ndSI8QtWpQGqxqFVPV8%3D&reserved=0

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAzureAD%2Fazure-activedirectory-library-for-dotnet%2Fissues%2F1130%23issuecomment-406250380&data=02%7C01%7CBogdan.Gavril%40microsoft.com%7C210935162869487d323008d5ed6e7ddf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636675981171095971&sdata=FEsnrX9YgIsiGzyM8s0xB9YWnQ1QJIDRspN%2BhYbvB4g%3D&reserved=0, or mute the threadhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FALtG6OXdnDhah8hWMw1I7PgMs8yv1zk0ks5uIHOjgaJpZM4VO_bS&data=02%7C01%7CBogdan.Gavril%40microsoft.com%7C210935162869487d323008d5ed6e7ddf%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636675981171105992&sdata=TPDbwq1I9S%2FKHfYs2ZwDgMpPz3Db4KBaV5%2BvEKmnFD0%3D&reserved=0.

sgiovinetti commented 6 years ago

@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 commented 6 years ago

@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 commented 6 years ago

@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 commented 6 years ago

@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 commented 6 years ago

@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.