c# - Blazor 独立 WASM 无法使用 MSAL 获取访问 token

标签 c# .net-core azure-ad-b2c msal blazor-webassembly

折腾了2天,投入了6个小时左右,我终于决定寻求帮助。
我有一个带有 MSAL 身份验证的独立 Blazor WASM 应用程序,在登录成功并尝试获取访问 token 后,我收到错误消息:

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
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();
        }
    }
我特意注释掉了 AuthorizationMessageHandler 的 HTTPClient 链接。
“AzureAD”配置具有设置为 true 的 Authority、ClientId 和 ValidateAuthority。
public class APIFunctionAuthorizationMessageHandler : AuthorizationMessageHandler
    {
        public APIFunctionAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigationManager)
        : base(provider, navigationManager)
        {
            ConfigureHandler(
                authorizedUrls: new[] { "<https://my_api_uri>" });
                //scopes: new[] { "FunctionAPI.Read" });
        }
    }
我已经尝试定义诸如 openid 或自定义 API 范围之类的范围,但现在没有。没有不同。
然后导致异常,我正在做的事情很简单:
@code {
    private string AccessTokenValue;

    protected override async Task OnInitializedAsync()
    {
        var accessTokenResult = await TokenProvider.RequestAccessToken();
        AccessTokenValue = string.Empty;

        if (accessTokenResult.TryGetToken(out var token))
        {
            AccessTokenValue = token.Value;
        }
    }
}

最终目标是使用这样的东西:
   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 请求或返回访问 token ,但假设这是 AuthorizationMessageHandler 作业。
非常感谢任何欢迎。
谢谢。

最佳答案

发现问题。
在 JavaScript 端做了一些调试后,文件 AuthenticationService.js,美化后第 171 行的方法“async getTokenCore(e)”,我已经确认实际上没有返回访问 token ,只有 IdToken。
通过阅读有关向 Azure AD B2C 请求访问 token 的文档,它提到根据您定义的范围,它将更改返回给您的内容。
范围“openid”告诉它您需要一个 IdToken,然后“offline_access”告诉它您需要一个刷新 token ,最后有一个绝妙的技巧,您可以在其中定义 App Id 的范围,它会返回一个访问 token 。
更多详情: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”。
现在错误没有发生并且返回了访问 token 。
谢谢。

关于c# - Blazor 独立 WASM 无法使用 MSAL 获取访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68553637/

相关文章:

c# - 使用 Validator 属性(或替代属性)来验证结构

azure - 使用自定义属性在 Azure AD B2C 中存储有关用户的附加信息

c# - Azure AD B2C .Net SDK - 通过电子邮件检索用户

c# - 将事件附加到动态对象

c# - 我怎么知道文本文件是否以回车结尾?

c# - 如何防止WebView2(Edge based)打开新窗口

C# AWS S3 上传损坏的文件

asp.net-mvc - ViewData 始终为空

c# - 使用 Roslyn CSharpCompilation 生成 .NET Standard 2.0 DLL

azure - 无法在 Azure 门户中创建 AAD B2C Yahoo OpenID Connect