title: Power BI Embed appears to be literally impossible to authenticate in a Blazor Webassembly application
body: <p>My team and I have tried this every way we can think of. Nothing has worked. We're ready to give up.</p>
  <p><strong>Attempt 1</strong> - a POST request using HttpClient():</p>
  <pre><code>public class PowerBIComponent : ComponentBase
  {
      [Inject] IConfiguration Config { get; set; }
  
      protected async override Task OnAfterRenderAsync(bool firstRender)
      {
          if (firstRender)
          {
              var token = await GetAccessToken();
          }
      }
  
      public async Task&lt;string&gt; GetAccessToken()
      {
          var form = new Dictionary&lt;string, string&gt;();
  
          form[&quot;grant_type&quot;] = &quot;client_credentials&quot;;
          form[&quot;client_id&quot;] = Config[&quot;PowerBI:ClientId&quot;];
          form[&quot;client_secret&quot;] = Config[&quot;PowerBI:ClientId&quot;];
          form[&quot;scope&quot;] = &quot;https://graph.microsoft.com/.default&quot;;
  
          var formContent = new FormUrlEncodedContent(form);
  
          using (var client = new HttpClient())
          {
              client.DefaultRequestHeaders.TryAddWithoutValidation(&quot;Content-Type&quot;, &quot;application/x-www-form-urlencoded&quot;);
  
              var response = await client.PostAsync(Config[&quot;PowerBI:AuthorityUrl&quot;], formContent);
  
              return response.Content.ToString();
          }
      }
  }
  </code></pre>
  <p>This produces the following error:</p>
  <p><code>Access to fetch at 'https://login.microsoftonline.com/{our-tenant-id}/oauth2/token' from origin 'https://localhost:44364' 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.</code></p>
  <p>Our infra guy has configured every allowable origin imaginable and it still hasn't resolved this issue. Bafflingly, the exact same request works just fine in Postman.</p>
  <p><strong>Attempt 2</strong> - using the Microsoft.PowerBI.API library:</p>
  <pre><code>public class PowerBIComponent : ComponentBase
  {
      [Inject] IConfiguration Config { get; set; }
  
      protected async override Task OnInitializedAsync()
      {
          Task.Delay(10000);
      }
  
      protected async override Task OnAfterRenderAsync(bool firstRender)
      {
          if (firstRender)
          {
              var token = await GetAccessToken();
          }
      }
  
      public async Task&lt;string&gt; GetAccessToken()
      {
          var appConfidential = ConfidentialClientApplicationBuilder.Create(Config[&quot;PowerBI:ClientId&quot;])
                              .WithClientSecret(Config[&quot;PowerBI:ClientSecret&quot;])
                              .WithAuthority(Config[&quot;PowerBI:AuthorityUrl&quot;])
                              .Build();
              
          string[] scopesDefault = new string[] { &quot;https://graph.microsoft.com/.default&quot; };
  
          var authResult = appConfidential.AcquireTokenForClient(scopesDefault).ExecuteAsync().Result;
  
          return authResult.AccessToken;
      }
  }
  </code></pre>
  <p>This produces the following error:</p>
  <p><code>crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Property UseDefaultCredentials is not supported.</code></p>
  <p>A quick google search led to <a href="https://developercommunity.visualstudio.com/t/blazor-webassembly-is-not-compatible-with-msalnet/903486" rel="nofollow noreferrer">this post</a>, which seems to suggest that this is an unavoidable compatibility issue in the library itself that has yet to be resolved.</p>
  <p><strong>Attempt 3</strong> - JSInterop and plain old Javascript:</p>
  <pre><code>window.PowerBI = {
  getAccessToken: function () {
      var form = {
          grant_type: &quot;client_credentials&quot;,
          client_id: &quot;my_super_secret_client_id&quot;,
          client_secret: &quot;my_super_duper_client_secret&quot;,
          scope: &quot;https://graph.microsoft.com/.default&quot;
      }
  
      $.ajax({
          url: 'https://login.microsoftonline.com/my-tenant-id-goes-here/oauth2/token',
          type: &quot;POST&quot;,
          contentType: 'application/x-www-form-urlencoded',
          data: form,
          success: function (result) {
              console.log(result);
          },
          error: function (xhr, resp, text) {
              console.log(xhr, resp, text);
          }
      });
  }
  </code></pre>
  <p>This produces the same CORS error we were getting using HttpClient():</p>
  <p><code>Access to XMLHttpRequest at 'https://login.microsoftonline.com/dccb27bf-99c4-4985-b8d7-7581887a825e/oauth2/token' from origin 'https://localhost:44334' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.</code></p>
  <p>We are quite simply trying to embed a Power BI report in our Blazor Webassembly application, however it seems to be categorically impossible to even get past the stage of retrieving an access token with which to embed anything. We're essentially at the point of giving up on Webassembly entirely and attempting to move everything over to Blazor Server instead. Is there any hope of us not having to do that?</p>