When we tried to embed ‘Power BI embedded’ in our existing application, we encountered a 406 not accepted error. To ensure that this was not caused by our own application we used the sample code in the power bi sample repository: https://github.com/Microsoft/PowerBI-Developer-Samples. We used the "App Owns Data" scenario, because our end users do not own Power BI Pro licenses. We followed all the necessary configuration steps and provided the necessary credentials/id's in the web.config.
At our first attempt to run the application, we got a connection closed error. After some research, we found out that this was caused by an incorrect TLS version. Adding ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
to the controller solved this.
The next error we faced was at the following line of code:
var authenticationResult = await authenticationContext.AcquireTokenAsync(ResourceUrl, ApplicationId, credential);
This line ended in an http exception: 406 - Not Acceptable. When we inspected the traffic with Fiddler, this error was deemed logical, because our Azure AD is referring to our ADFS server as the relying party with an accept header for JSON content, while our ADFS returned an xml body. Our conclusion was that the AcquireTokenAsync does not work correctly with our corporate Azure AD / ADFS environment. To investigate this, we ran several tests:
Instead of using the standard ADAL library, we tried to use the MSAL lib. However, this resulted in the same error.
Doing a (raw) post request to the Azure AD to obtain the auth token with the following code:
try { client.DefaultRequestHeaders.Add("Cache-Control", "no-cache"); _result = await client.PostAsync( new Uri("https://login.windows.net/common/oauth2/token"), new FormUrlEncodedContent( new[] { new KeyValuePair("resource", "https://analysis.windows.net/powerbi/api"), new KeyValuePair("client_id", ClientId), new KeyValuePair("grant_type", "password"), new KeyValuePair("username", UserName), new KeyValuePair("password", Password), new KeyValuePair("scope", "openid"), })); } catch (HttpOperationException ex) { //Bad Request var content = ex.Response.Content; Console.WriteLine(content); }
This resulted in the following error, which we were not able to solve:
{"error":"invalid_grant","error_description":"AADSTS70002: Error validating credentials. AADSTS50126: Invalid username or password\r\nTrace ID: b8a97eae-63a4-4d56-8afd-e18eb7b02800\r\nCorrelation ID: 3e168d8f-61ab-4b7f-b9c4-6ae7870c5e06\r\nTimestamp: 2018-12-03 12:59:38Z","error_codes":[70002,50126],"timestamp":"2018-12-03 12:59:38Z","trace_id":"b8a97eae-63a4-4d56-8afd-e18eb7b02800","correlation_id":"3e168d8f-61ab-4b7f-b9c4-6ae7870c5e06"}
We performed an interactive logon by using the following code with success:
var authenticationResult = await authenticationContext.AcquireTokenAsync(ResourceUrl, ApplicationId, new Uri("http://localhost:42734/"), new PlatformParameters(PromptBehavior.Auto));
However, this is not ideal, because we do not want our end-users to (interactively) login with a proxy account in our AD every time they use Power BI embedded in our application :)
- Following the blog from microsoft about this scenario also yielded no results: https://blogs.msdn.microsoft.com/azuredev/2018/01/22/accessing-the-power-bi-apis-in-a-federated-azure-ad-setup/
The question was how to fix this.... See the answer below that we found after months (!) of searching.