Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Critical error out of the box. #21640

Closed
brettrig opened this issue Feb 27, 2021 · 15 comments · Fixed by #21643
Closed

Critical error out of the box. #21640

brettrig opened this issue Feb 27, 2021 · 15 comments · Fixed by #21643
Assignees
Labels
Blazor doc-enhancement Pri1 Source - Docs.ms Docs Customer feedback via GitHub Issue

Comments

@brettrig
Copy link

Hi there,

I've followed the details in this blog post to the letter and I get a critical error:

Log in using Azure B2C works fine - am authenticated as expected.
Call off to the Server API fails on the Weather Forecast page.

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()
   at System.Text.Json.Serialization.Converters.DateTimeOffsetConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
   at System.Text.Json.JsonPropertyInfo`1[[System.DateTimeOffset, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessToken, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, AccessToken& value)
   at System.Text.Json.Serialization.JsonConverter`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessToken, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, AccessToken& value)
   at System.Text.Json.JsonPropertyInfo`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessToken, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, InternalAccessTokenResult& value)
   at System.Text.Json.Serialization.JsonConverter`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, InternalAccessTokenResult& value)
   at System.Text.Json.Serialization.JsonConverter`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
   at System.Text.Json.Serialization.JsonConverter`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.Serialization.JsonConverter`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].ReadCoreAsObject(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadCore[Object](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadValueCore[Object](JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state)
   at System.Text.Json.JsonSerializer.Deserialize(Utf8JsonReader& reader, Type returnType, JsonSerializerOptions options)
   at Microsoft.JSInterop.JSRuntime.EndInvokeJS(Int64 taskId, Boolean succeeded, Utf8JsonReader& jsonReader)
   --- End of inner exception stack trace ---
   at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__15`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].MoveNext()
   at Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationService`3.<RequestAccessToken>d__22[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationState, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteUserAccount, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.Authentication.WebAssembly.Msal.Models.MsalProviderOptions, Microsoft.Authentication.WebAssembly.Msal, Version=5.0.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].MoveNext()
   at Microsoft.AspNetCore.Components.WebAssembly.Authentication.AuthorizationMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
   at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__9`1[[BlazorHostedWebAsmB.Shared.WeatherForecast[], BlazorHostedWebAsmB.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
   at BlazorHostedWebAsmB.Client.Pages.FetchData.OnInitializedAsync() in C:\Demos\BlazorHostedWebAsmB\Client\Pages\FetchData.razor:line 48
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

Am I doing something wrong?? Would really like to use Blazor for my project, but am struggling big time to overcome simple hurdles like this.

Thanks,

Brett


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@dotnet-bot dotnet-bot added ⌚ Not Triaged Blazor Source - Docs.ms Docs Customer feedback via GitHub Issue labels Feb 27, 2021
@guardrex guardrex self-assigned this Feb 27, 2021
@guardrex
Copy link
Collaborator

Hello @riggadon ... WRT "in this blog post" ... if you mean this topic, ok. If you're referring to something else, we don't support external topics/blog posts here.

WRT to this topic and this error that you're seeing, I don't have further information on this at this time outside of the product unit issue that was opened at ...

dotnet/aspnetcore#28487

There's a remark at the end that might be helpful (and you can ask that community member further on that issue about it) at ...

I dropped the API permission from the app and re-added it.

dotnet/aspnetcore#28487 (comment)

... which I think refers to dropping and re-adding the API permission in the Azure portal registration.

In general, this documentation has been working, but there are times when a slight app or Azure misconfiguration, alternative use case, or edge case has caused problems. If you follow that last remark there ☝️ (drop and re-add the API permission in Azure), I recommend mentioning that you tried it when you comment there. I'm watching 👀 that issue to see if a doc update can help. At this time tho, there's nothing actionable to document. We need more information on what's causing the problem. Eventually if it works out that this issue is solved by dropping and re-adding the API permission in the portal, then I'll add a remark on it to the Troubleshoot section of this topic.

@guardrex
Copy link
Collaborator

... also @riggadon ... make sure that you're following the guidance to use a fresh browser session for every single test run no matter how small the change to the app or to the Azure config. Lingering cookies can cause all sorts of foul behaviors.

@brettrig
Copy link
Author

brettrig commented Feb 27, 2021

@guardrex Thanks for the replies.

Yes, apologies, I did mean this topic - but despite dropping and re-adding the API permission in the Azure portal (as mentioned in #28487), it remains the same error that appears in the browser console (F12). I've stopped the web host and re-run it, forcing the browser to reload the content. Same error.

Originally tried in Edge, and reproduced the same behavior in Chrome.

@guardrex
Copy link
Collaborator

guardrex commented Feb 27, 2021

Ok ... it was worth a shot.

Comment on the engineering issue that you're having the same problem. I'm not sure why the discussion was dropped. It sort of looks like those who were hitting this error stopped hitting it or stopped using B2C+Blazor (i.e., they stopped asking, so Pranav didn't discuss it further with them).

@brettrig
Copy link
Author

Not to be beaten by this, I have made a little progress and think I might have found my cause of my issue.

The command line to produce the project is as follows:

dotnet new blazorwasm -au IndividualB2C --aad-b2c-instance "{AAD B2C INSTANCE}" --api-client-id "{SERVER API APP CLIENT ID}" --app-id-uri "{SERVER API APP ID URI}" --client-id "{CLIENT APP CLIENT ID}" --default-scope "{DEFAULT SCOPE}" --domain "{TENANT DOMAIN}" -ho -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"

...specifically, the {SERVER API APP ID URI} section.

In the Azure portal, within the AAD B2C section, when I added the Server application, it produced/generated a App ID URI in the format of:

https://myname.onmicrosoft.com/aaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

...so, feeding this URI into the above CLI command above produced the project as expect, which compiles and runs but fails to return data BUT with a slight repetition problem in the Client\Program.cs file, as follows:

builder.Services.AddMsalAuthentication(options =>
            {
                builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
                options.ProviderOptions.DefaultAccessTokenScopes.Add("https://myname.onmicrosoft.com/https://myname.onmicrosoft.com/aaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/API.Access");
            });

I've messed around a few times and found that either solution works:

  1. Remember to delete the duplicated address in the Program.cs files within the client project.
  2. Change the {SERVER API APP ID URI} element of the original CLI command to refer to the GUID instead of the entire address.

Haven't seen any unexpected effects of either as yet.

I can see the wording in the example description of the SERVER API APP ID URI you have specified that the value is of guid format, but I genuinely missed this until writing this reply, particularly as the instructions suggest to take note of the value from earlier.

ALSO - I needed to remember that if using Visual Studio, I had to change away from using the default IIS EXPRESS setting, as the default startup port isn't 5001. (Side issue, I guess)

@guardrex
Copy link
Collaborator

Yes, that's a known problem. I'll see if I can find the open issue on it. I think the plan was to address it for .NET 6. I'll report back.

@guardrex
Copy link
Collaborator

guardrex commented Feb 27, 2021

Actually ... no ... the issue that I opened was for a double scheme, and that's described in the topic and cross-linked.

https://docs.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/hosted-with-azure-active-directory-b2c?view=aspnetcore-5.0#create-the-app

feeding this URI into the above CLI command above produced the project as expect

If only the GUID is used with the command (as that section shows in an example ☝️), the resultant URI shouldn't have an extra "https://myname.onmicrosoft.com/" in there. EDIT: Actually, that doesn't address your use case, which is an untrusted publisher domain. I'm not sure how you ended up with the resultant URI like that. IIRC with an untrusted publisher domain, one puts in the full URI ... then they ONLY get the (wrong) double scheme. One doesn't get a full double domain like that.

WRT the double scheme ... I'm not sure if the duplicate scheme problem was limited to CLI, CLI for AAD only (i.e., Single Org only), or included VS. Part of the problem is that there are AAD vs. B2C and CLI vs. VS combinations of approaches. They don't all behave exactly the same way (or even work OOB in some cases, most notably in the VS case for Single Org). These deltas are being improved by the product unit, and I think ASP.NET Core 6.0 at the latest will include fixes.

WRT VS, we don't have the NOTE here that appears at the top of the ADD topic because (IIRC 🤔) it wasn't a problem for B2C apps. If you found a VS x B2C x Blazor created project problem, it would be a separate issue. Given that the topic doesn't rely on VS at this time, we'd only place a NOTE at the top calling out a problem with the way that VS is setting up the app. Again tho, I think if VS is given just the GUID that the URI config will come out correctly.

@guardrex
Copy link
Collaborator

guardrex commented Feb 27, 2021

I'll reach this topic for an overhaul pass on my tracking issue #19286 sometime in the next few months. I'll walk it all again and check the behaviors. I've marked this issue on the tracking issue so that I don't lose track of this.

@brettrig
Copy link
Author

Ah ok, great - Now I'm all working, I'll continue as I am for the moment, but will wait to see what .Net 6.0 brings with it. But it almost put me off of using Blazor entirely, as I was spend far too much time doing something that I know I can get sorted in a regular MVC site very quickly.

But in terms of the VS comment, I was meaning purely from a running/debugging perspective. I used the CLI to generate the initial project, but opened the .sln file up in VS2019 to run. If the default of IIS EXPRESS is used, then a 5-digit port number is used. But if the project is changed to use the Kestral server, then 5001 is used. But yes, this isn't anything to do with this, so please ignore this entirely.

@brettrig
Copy link
Author

Actually, that doesn't address your use case, which is an untrusted publisher domain. I'm not sure how you ended up with the resultant URI like that. IIRC with an untrusted publisher domain, one puts in the full URI ... then they ONLY get the (wrong) double scheme. One doesn't get a full double domain like that.

Untrusted publisher domain? Yeah, I don't know why that was generated like that. I've just rechecked the value in the Azure portal, and it's what was produced as part of the portal UI when exposing an API.

@guardrex
Copy link
Collaborator

guardrex commented Feb 27, 2021

Thanks for the discussion @riggadon ... it does help me understand how the topic is used and the sorts of things that we'll need to address. Eventually, I think the topic will move away from the use of the CLI and to VS, or we might end up with tabs for each tooling (VS, VS4Mac, VSC, CLI) and provide guidance for each.

WRT the untrusted publisher domain, that's normal ... if it's untrusted, of course. The other type of URI (e.g., api://{GUID}) is what that Azure portal provides for a trusted publisher domain. They have a doc in the Azure docs that explain more about the publisher domain, trusted and untrusted. I don't have the link tho ... you'd have search their docs for it.

When I said I didn't understand your value ... I didn't mean the URI. I meant the configuration in your app given that AFAIK the CLI command doesn't duplicate the domain (only the scheme) when passing the untrusted publisher domain. AFAIK when passing the domain, you end up with something like ...

api://https://myname.onmicrosoft.com/aaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/API.Access

... not ...

https://myname.onmicrosoft.com/https://myname.onmicrosoft.com/aaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/API.Access

I don't know if that's a new regression or just something unusual about the way that you had your CLI command set up.

spend far too much time doing something that I know I can get sorted in a regular MVC site very quickly.

Yes, it's rough because it's all so new. I think 6.0 will have a number of fixes, and I think VS project generation problems today will all be sorted out.

One of the things that I've noticed is that when any sort of error occurs, devs aren't very keen on looking at the app config or understanding what they see. The reasons are (I think) that devs assume the tooling, be it CLI, VS, or whatever, has done the right thing and not put a bad config into their app and/or they were 100% faithful to the guidance. Unfortunately, those two things often aren't the case. Most problems reported here have worked out to (a) foul config got into the app (sometimes Azure) and (b) the dev didn't look/notice/understand it. In your case, I think you didn't immediately pick up on the double domain of "https://myname.onmicrosoft.com/https://myname.onmicrosoft.com/" ... to a seasoned 👁️, it's clear ... but to everyone else new to this whole Blazor-B2C paradigm, that's not easy to spot and understand that it's not correct.

I'll continue to reason on how the docs can get devs to troubleshoot better. I have a feeling that I need to lead into specific troubleshooting guidance with a little section that speaks to this aspect and perhaps even shows (briefly) a valid config for a typical app. I'll work on it when I reach the topic for its UE (i.e., "user experience") pass shortly.

@guardrex
Copy link
Collaborator

guardrex commented Feb 27, 2021

It's actually there ... a little buried ... see the purple NOTE here ...

https://docs.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/hosted-with-azure-active-directory-b2c?view=aspnetcore-5.0#access-token-scopes

... that would help if it's seen. There's a lot here ... it's easy to miss any fine point.

I think I can quickly 🏃 do something for this in the Troubleshoot section to reinforce the earlier guidance in the topic.

@duyvt88
Copy link

duyvt88 commented Jun 27, 2022

Hi all,
I still got the same issue on Blazor .Net Core 6. I think it is fixed by this commit #21643 but I am not sure how to use that fix on my project. Could anyone give me a guide?

Many thanks,

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.

@guardrex
Copy link
Collaborator

@duyvt88 ... Take a look at dotnet/aspnetcore#39311 to see if that helps.

@duyvt88
Copy link

duyvt88 commented Jun 27, 2022

@guardrex I think it is not fixed. We may need to wait for the new .Net Core 7 version.
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Blazor doc-enhancement Pri1 Source - Docs.ms Docs Customer feedback via GitHub Issue
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants