简体   繁体   中英

Power BI embed API access token request works through Postman but not through code

I'm working on embedding a Power BI dashboard into a Blazor web application, but I seem to be completely stuck on retrieving the access token. I'm using the following code, as taken from this tutorial and modified to use client credentials in place of a password:

private async Task<string> GetPowerBIAccessToken()
{
    using (var client = new HttpClient())
    {
        var form = new Dictionary<string, string>();

        form["grant_type"] = "client_credentials";
        form["client_id"] = _configuration["PowerBI:ApplicationId"];
        form["client_secret"] = _configuration["PowerBI:ApplicationSecret"];
        form["scope"] = "https://graph.microsoft.com/.default";

        client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");

        var request = new HttpRequestMessage();

        request.SetBrowserRequestMode(BrowserRequestMode.NoCors);
        request.Method = HttpMethod.Post;
        request.RequestUri = new Uri(_configuration["PowerBI:AuthorityUrl"]);
        request.Content = new FormUrlEncodedContent(form);

        using (var response = await client.SendAsync(request))
        {
            var body = await response.Content.ReadAsStringAsync();
            var jsonBody = JObject.Parse(body);
            var errorToken = jsonBody.SelectToken("error");
            if (errorToken != null)
            {
                throw new Exception(errorToken.Value<string>());
            }
            return jsonBody.SelectToken("access_token").Value<string>();
        }
    }
}

This code produces the following error in the browser: Unhandled exception rendering component: Error reading JObject from JsonReader. Path '', line 0, position 0. Unhandled exception rendering component: Error reading JObject from JsonReader. Path '', line 0, position 0. .

This is because the line var jsonBody = JObject.Parse(body) is attempting to parse the JSON response, but the response is empty. Perplexingly, this is not because the request fails - in fact it returns a 200, but with a completely blank response body:

请求标头和表单数据

空白回复

Even more perplexingly, the exact same request reconstructed in Postman returns the result just fine:

成功的邮递员请求和响应

I'm sure there's some basic difference between Postman and my code that I'm overlooking, but I've been banging my head against this for hours with no luck. I'd hugely appreciate any guidance. Thanks very much in advance.

This could potentially be an issue with your security settings

I'm an idiot. I'm getting an opaque response because that's exactly how I've configured the request.

The whole reason I ran up against this problem was that I was encountering a CORS error when trying to make the original request:

Access to fetch at 'https://login.microsoftonline.com/cattywampus.microsoftonline.com/oauth2/token' from origin 'https://localhost:44333' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I consequently added request.SetBrowserRequestMode(BrowserRequestMode.NoCors) to the configuration, not understanding that an opaque response means the response will be blank, regardless of the outcome.

Clearly this didn't solve anything for me. If you run up against the above error message, be sure you know that an opaque response means that even a 200 won't return any kind of payload. That's what's meant by opaque. At least I learned something today.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM