Blazor独立WASM无法使用MSAL获取访问令牌

c#

折腾了2天,投入了6个小时左右,我终于决定寻求帮助。

我有一个带有 MSAL 身份验证的独立 Blazor WASM 应用程序,在登录成功并尝试获取访问令牌后,我收到错误消息:

blazor.webassembly.js:1 info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
      Authorization was successful.
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: An exception occurred executing JS interop: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 73.. See InnerException for more details.
Microsoft.JSInterop.JSException: An exception occurred executing JS interop: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 73.. See InnerException for more details.
 ---> System.Text.Json.JsonException: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 73.
 ---> System.InvalidOperationException: Cannot get the value of a token type 'Null' as a string.
   at System.Text.Json.Utf8JsonReader.TryGetDateTimeOffset(DateTimeOffset& value)
   at System.Text.Json.Utf8JsonReader.GetDateTimeOffset()
blazor.webassembly.js:1 info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
      Authorization was successful.
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: An exception occurred executing JS interop: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 73.. See InnerException for more details.
Microsoft.JSInterop.JSException: An exception occurred executing JS interop: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 73.. See InnerException for more details.
 ---> System.Text.Json.JsonException: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 73.
 ---> System.InvalidOperationException: Cannot get the value of a token type 'Null' as a string.
   at System.Text.Json.Utf8JsonReader.TryGetDateTimeOffset(DateTimeOffset& value)
   at System.Text.Json.Utf8JsonReader.GetDateTimeOffset()

此错误仅在我登录后显示。

我的设置在 .NET 5.0 上运行,身份验证提供程序是 Azure B2C 租户,我将重定向 URI 正确配置为“单页应用程序”,并将权限授予“offline_access”和“openid”。

这是我的 Program.cs

我特意注释掉了 AuthorizationMessageHandler 的 HTTPClient 链接。“AzureAD”配置具有设置为 true 的 Authority、ClientId 和 ValidateAuthority。

public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");

            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

            // Authenticate requests to Function API
            builder.Services.AddScoped<APIFunctionAuthorizationMessageHandler>();
            
            //builder.Services.AddHttpClient("MyAPI", 
            //    client => client.BaseAddress = new Uri("<https://my_api_uri>"))
            //  .AddHttpMessageHandler<APIFunctionAuthorizationMessageHandler>();

            builder.Services.AddMudServices();

            builder.Services.AddMsalAuthentication(options =>
            {
                // Configure your authentication provider options here.
                // For more information, see https://aka.ms/blazor-standalone-auth
                builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);

                options.ProviderOptions.LoginMode = "redirect";
                options.ProviderOptions.DefaultAccessTokenScopes.Add("openid");
                options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access");
            });

            await builder.Build().RunAsync();
        }
    }

我已经尝试定义诸如 openid 或自定义 API 范围之类的范围,但现在没有。没有不同。

然后导致异常,我正在做的事情很简单:

public class APIFunctionAuthorizationMessageHandler : AuthorizationMessageHandler
    {
        public APIFunctionAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigationManager)
        : base(provider, navigationManager)
        {
            ConfigureHandler(
                authorizedUrls: new[] { "<https://my_api_uri>" });
                //scopes: new[] { "FunctionAPI.Read" });
        }
    }

最终目标是使用这样的东西:

   try {
      var httpClient = ClientFactory.CreateClient("MyAPI");
      var resp = await httpClient.GetFromJsonAsync<APIResponse>("api/Function1");
      FunctionResponse = resp.Value;
      Console.WriteLine("Fetched " + FunctionResponse);
   }
   catch (AccessTokenNotAvailableException exception)
   {
      exception.Redirect();
   }

但是返回了相同的错误,甚至在运行之前看起来如此。此代码也是 Blazor 组件的 OnInitializedAsync()。

欢迎任何想法或建议。我被困住了,有点绝望。

我怀疑没有从 Azure AD B2C 请求或返回访问令牌,但假设这是 AuthorizationMessageHandler 作业。

非常感谢任何欢迎。

谢谢。

回答

发现问题。

在 JavaScript 端做了一些调试后,文件 AuthenticationService.js,美化后第 171 行的方法“async getTokenCore(e)”,我已经确认实际上没有返回访问令牌,只有 IdToken。

在阅读有关向 Azure AD B2C 请求访问令牌的文档时,它提到根据您定义的范围,它将更改返回给您的内容。

范围“openid”告诉它您需要一个 IdToken,然后“offline_access”告诉它您需要一个刷新令牌,最后有一个绝妙的技巧,您可以在其中定义 App Id 的范围,它会返回一个访问令牌。更多详细信息:https : //docs.microsoft.com/en-us/azure/active-directory-b2c/access-tokens#openid-connect-scopes

所以我在 Program.cs、builder.Services.AddMsalAuthentication 步骤中更改了我的代码。

现在它看起来像这样:

builder.Services.AddMsalAuthentication(options =>
            {
                // Configure your authentication provider options here.
                // For more information, see https://aka.ms/blazor-standalone-auth
                builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);

                options.ProviderOptions.LoginMode = "redirect";
                options.ProviderOptions.DefaultAccessTokenScopes.Add("00000000-0000-0000-0000-000000000000");
                //options.ProviderOptions.DefaultAccessTokenScopes.Add("openid");
                //options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access");
            });

我设置了我在这个 Blazor 应用程序上使用的实际应用程序 ID,而不是“00000000-0000-0000-0000-000000000000”。

现在错误没有发生并且返回了访问令牌。

谢谢。


以上是Blazor独立WASM无法使用MSAL获取访问令牌的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>