Closed vsfeedback closed 2 years ago
Thanks for contacting us. This is already fixed as part of #38962 / https://github.com/dotnet/aspnetcore/pull/39060.
Please note, the fix for this issue should be available in the 6.0.2 patch release.
Any estimates on this? I've got this installed 6.0.200-preview.21617.4 and still not working
The fix for the underlying System.Text.Json.JsonException: Invalid JSON
exception was backported through https://github.com/dotnet/aspnetcore/pull/39075.
@rmencia-isv could you please try this out using the latest installer available at https://github.com/dotnet/installer. Please let us know if you're still having the issue with that, and please provide the exact version of the dotnet sdk being used, along side the exact exception message you're getting.
I have installed the latest versionfrom the url you provided (dotnet-sdk-6.0.200-preview.22068.4-win-x64.exe) and I still get the same error in Blazor wasm client app.
Checking the list I have this one installed (6.0.200-preview.22068.4) However, by looking at the call stack I see references to Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.1.0*
The error Message: 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.
InnerException:
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.Serialization.JsonConverter1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.1.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=6.0.1.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.Read[Object](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo)
at System.Text.Json.JsonSerializer.Deserialize(Utf8JsonReader& reader, Type returnType, JsonSerializerOptions options)
at Microsoft.JSInterop.JSRuntime.EndInvokeJS(Int64 taskId, Boolean succeeded, Utf8JsonReader& jsonReader)'
by looking at the call stack I see references to Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.1.0*
Ah that's definitely a bit strange. Could you please double check your csproj files to ensure you don't have any hardcoded versions which may be causing this issue? Also, if you could try adding the following to your nuget config:
<add key="dotnet6" value="https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet6/nuget/v3/index.json" />
Further details here.
This is what I have in the project file. I also added the nuget in VS to get the packages from that place and no new updates available, even pre-release for any of those packages.
Hey @rmencia-isv, I took a look at the feeds and you're right the 6.0.2 (prerelease) packages aren't up yet. You can either try waiting for the official 6.0.2 release (mid February), or try the 7.0 alpha packages (not sure if they'll be updated yet though).
Thanks Tanay for getting back to me. It's unfortunate that the packages are not uploaded yet, as I've seen a number of issues fixed. I'll probably wait for the release next month, if the pre release packages are not updated.
Hi, @TanayParikh ,
I'm facing the same issue. Unfortunately I cannot wit until mid February. Is there any chance to test the 6.0.2 (prerelease) you mentioned.
This is definitively not present on the repo you suggested...
Hello @kbeaugrand, to test out the pre-release you can try using the nightly SDK & packages as above, or by using the 7.0 alpha/beta packages.
SDK Download: https://github.com/dotnet/installer (ensure you get the 6.0.2 or 7 alpha/beta SDK)
Add to your Nuget config:
<add key="dotnet6" value="https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet6/nuget/v3/index.json" />
Further details here.
I also am having the exact same issue with B2C and Blazor WASM. Hope they release the fix soon. I'm hesitant to install preview builds.
Hi @TanayParikh,
Do you have a more precise date for the release of Microsoft.AspNetCore.Components.WebAssembly.Authentication v6.0.2 ?
Thank you.
Hi @TanayParikh,
Do you have a more precise date for the release of Microsoft.AspNetCore.Components.WebAssembly.Authentication v6.0.2 ?
Thank you.
It was just released earlier today!
Hi @TanayParikh, Do you have a more precise date for the release of Microsoft.AspNetCore.Components.WebAssembly.Authentication v6.0.2 ? Thank you.
It was just released earlier today!
Thank you for your answer. I checked it, but unfortunately I'm still facing the issue... ;(
unfortunately I'm still facing the issue
To confirm you've updated the SDK/.csproj to utilize the new 6.0.2 packages, correct? What exact error message are you seeing?
Can you please provide a minimal, public, github repro which reproduces this issue?
unfortunately I'm still facing the issue
To confirm you've updated the SDK/.csproj to utilize the new 6.0.2 packages, correct? What exact error message are you seeing?
Can you please provide a minimal, public, github repro which reproduces this issue?
Hi,
Yes I confirm that I updated my package to 6.0.2 (https://github.com/CGI-FR/IoT-Hub-Portal/blob/main/src/AzureIoTHub.Portal/Client/AzureIoTHub.Portal.Client.csproj). I'm using OpenID connect.
You can find a public repos (not minimal) with my configuration here: https://github.com/CGI-FR/IoT-Hub-Portal/.
For the code sample, that is relevant, you can find at client Program.cs file the executed configuration: https://github.com/CGI-FR/IoT-Hub-Portal/blob/main/src/AzureIoTHub.Portal/Client/Program.cs.
The error message obtained is:
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: 170.. 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: 170.. 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: 170.
---> 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.Serialization.Metadata.JsonPropertyInfo`1[[System.DateTimeOffset, System.Private.CoreLib, Version=6.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=6.0.2.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=6.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, AccessToken& value)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessToken, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.2.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=6.0.2.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=6.0.2.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=6.0.2.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=6.0.2.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=6.0.2.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.Read[Object](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo)
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__16`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.2.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=6.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteUserAccount, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.AspNetCore.Components.WebAssembly.Authentication.OidcProviderOptions, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.2.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.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__13`1[[AzureIoTHub.Portal.Shared.Models.Device.DeviceListItem[], AzureIoTHub.Portal.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at AzureIoTHub.Portal.Client.Pages.Devices.DeviceListPage.LoadDevices() in C:\Users\beaugrandk\Source\Repos\CGI-FR\IoT-Hub-Portal\src\AzureIoTHub.Portal\Client\Pages\Devices\DeviceListPage.razor:line 179
at AzureIoTHub.Portal.Client.Pages.Devices.DeviceListPage.OnInitializedAsync() in C:\Users\beaugrandk\Source\Repos\CGI-FR\IoT-Hub-Portal\src\AzureIoTHub.Portal\Client\Pages\Devices\DeviceListPage.razor:line 163
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
window.Module.s.printErr @ blazor.webassembly.js:1```
I may be able to reproduce the issue on a minimal project if needed.
I may be able to reproduce the issue on a minimal project if needed.
Yes please, that'd be much appreciated!
Thanks for the stack trace. I see the underlying System.Text.Json.JsonException: Invalid JSON
is resolved (via backported https://github.com/dotnet/aspnetcore/pull/39075), but we still have the
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: 170.. 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: 170.
---> System.InvalidOperationException: Cannot get the value of a token type 'Null' as a string.
error. Re-opening this issue.
I may be able to reproduce the issue on a minimal project if needed.
Yes please, that'd be much appreciated!
Thanks for the stack trace. I see the underlying
System.Text.Json.JsonException: Invalid JSON
is resolved (via backported #39075), but we still have theMicrosoft.JSInterop.JSException: An exception occurred executing JS interop: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires | LineNumber: 0 | BytePositionInLine: 170.. 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: 170. ---> System.InvalidOperationException: Cannot get the value of a token type 'Null' as a string.
error. Re-opening this issue.
I'll send you the sample app as soon I've pushed on a public repos.
I was so happy when I saw this should have been fixed.
Guess I will have to wait a little more with the auth implementation.
Hi @mkArtakMSFT @TanayParikh ,
I saw that nothing changed here (and I forget to push the sample repository).
This is available herehttps://github.com/kbeaugrand/SampleOpenIDConnect
I'm using Okta identity provider, the settings are present at Program.cs#L16-21
This is available herehttps://github.com/kbeaugrand/SampleOpenIDConnect
Hi @kbeaugrand, could you please confirm the Repo is still available and is public? I'm getting a 404 when I try to access that URL.
My bad, it was private. Now it should be ok
Thanks. Looks like it's an issue with the deserialization of the DateTimeOffset
of the AccessToken
here:
which is a part of
which gets called here:
on the client side, this translates to:
which doesn't define AccessToken.Expires
, which may be why the deserialization is failing.
For the non-MSAL case:
on the client side, this translates to:
which gets the Expires
via:
Based on this, does Expires
really need to be a DateTimeOffset
vs. DateTime
? cc/ @javiercn
Based on https://docs.microsoft.com/dotnet/standard/datetime/system-text-json-support we may be dealing with non compliant DateTimeOffset
values.
Attempting to read non-compliant formats with Utf8JsonReader will cause it to throw a FormatException:
// Unhandled exception. System.FormatException: The JSON value is not in a supported DateTime format.
@kbeaugrand can you please confirm what needs to be done to trigger the exception you're seeing, using the repro you provided? I just end up with an Okta 404 when I try to run your project.
@TanayParikh,
After configuring the OIDC settings for your tenant, and launching the project with Visual Studio, go to https://localhost:7002/fetchdata, you will have the issue present on log from the broswser developper console.
As a sample, you can verify my id_token that wahs provided by okta:
eyJraWQiOiI1YzlnblA3Wk1qbDY0NzdFTEl1VDlyNUpKYi0zLXhBNi04Q2x6akdWY0RJIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiIwMHU0Zm9xdmp0Rkd3c1lvajVkNyIsIm5hbWUiOiJkZW1vIGRlbW8iLCJsb2NhbGUiOiJlbl9VUyIsInZlciI6MSwiaXNzIjoiaHR0cHM6Ly9kZXYtMDc0NjEzMTAub2t0YS5jb20vb2F1dGgyL2RlZmF1bHQiLCJhdWQiOiIwb2E0Zm9yZTdqcGhLRDlHaTVkNyIsImlhdCI6MTY0OTE4ODc2NSwiZXhwIjoxNjQ5MTkyMzY1LCJqdGkiOiJJRC5vU2FlLVo1YWpjTXI3TW1OS3A5ckZCZVhLZi1uMUZCWG5uSEg1Y1FsTkd3IiwiYW1yIjpbInB3ZCJdLCJpZHAiOiIwMG80Zm0zeGV0NkRYQzVxZjVkNyIsIm5vbmNlIjoiZjU1NGE2ZjY3YTgxNDE3OWJhMzdlZmMxNWJhZDk4NWIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJrYmVhdWdyYW5kQGdtYWlsLmNvbSIsImdpdmVuX25hbWUiOiJkZW1vIiwiZmFtaWx5X25hbWUiOiJkZW1vIiwiem9uZWluZm8iOiJBbWVyaWNhL0xvc19BbmdlbGVzIiwidXBkYXRlZF9hdCI6MTY0ODY0ODk0NSwiYXV0aF90aW1lIjoxNjQ5MTg4NzY0fQ.aa5Cf5nHAm5QwcMaYgtCbU6Tnsub1H29AO-qtnFyOgzh_gY9oig1TxL-LwjiOB0nbMPODUF1Gkku90pAKql2j-zr5vGIoMN6886ZC8avMQn0ra-L6LFn00M_hNPJdWJCyXk9cUVsfkwoD6lqiiZHDDpuh4b59_R6DtLQl8jXES8i7jWiELLSXhe09tTMZy4COa0W6HxrMp2ahNXi954sFvHjkxZeXkpVrOCRUm0Lhzrm2M-hT2VaJ_YlTC78VUUI3eEOlBDqTCuBqyVrL8Q8IEk1tZs8y_LVsseMVkE6ho6kPCpHHdvc561XtmfvIkpVr4pFT8QIhVb7_Z8Jo6LfAw&state=797a8d10e2e647c09530765137eecd16
Don't worry, this doesn't give access to anything.. ;)
@TanayParikh
Thanks. Looks like it's an issue with the deserialization of the
DateTimeOffset
of theAccessToken
here:which is a part of
which gets called here:
on the client side, this translates to:
which doesn't define
AccessToken.Expires
, which may be why the deserialization is failing.For the non-MSAL case:
on the client side, this translates to:
which gets the
Expires
via:Based on this, does
Expires
really need to be aDateTimeOffset
vs.DateTime
? cc/ @javiercn
I think this doesn't comes from the deserialization of the access_token
.
In my configuration I only get the ID Token from the IDP. The issue occurs while getting the access token. at that time I have no network requests from the browser...
From the Blazor WASM when calling var tokenRequest = await TokenProvider.RequestAccessToken();
i get the following error:
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()
at System.Text.Json.Serialization.Converters.DateTimeOffsetConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1[[System.DateTimeOffset, System.Private.CoreLib, Version=6.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=6.0.2.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=6.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, AccessToken& value)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessToken, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.2.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=6.0.2.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=6.0.2.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=6.0.2.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=6.0.2.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=6.0.2.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.Read[Object](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo)
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__16`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.2.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=6.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteUserAccount, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.Authentication.WebAssembly.Msal.Models.MsalProviderOptions, Microsoft.Authentication.WebAssembly.Msal, Version=6.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].MoveNext()
at BforBoat.Web.Pages.Profile.OnInitializedAsync() in C:\Projects\vsts\mikaelsyska\bforboat\src\BforBoat.Web\Pages\Profile.razor.cs:line 29
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
( If, I can include the actual response from the IDP )
This is the response returned from Azure B2C ...
Do we have any known workaround to handle this issue till it is officially fixed?
Do we have any known workaround to handle this issue till it is officially fixed?
Unfortunatly not at this time... ;(
I'm affected by this issue too.
Would be nice if this could be scheduled into one of the next releases.
Using 6.0.4 and I'm affected by this issue too. Any timeline on a fix?
The symptoms I'm getting is after being redirected back from Azure AD B2C, I can see the token being sent, from login-callback the app then moves to login-fail.
Yet the app then seems to then try refreshing a couple of times.
Some of the API calls work then it falls over on the third one with a 401.
Is this a symptom of the same issue?
@mkArtakMSFT @TanayParikh any update ?
@kbeaugrand we are looking into it, but it seems the issue happens when the app is not requesting an access token.
@kbeaugrand we are looking into it, but it seems the issue happens when the app is not requesting an access token.
Thank you @javiercn, Is there a workaround ?
@kbeaugrand You can likely avoid this issue if you request an access token for the app.
Alternatively you can provide your own JS based on https://github.com/dotnet/aspnetcore/blob/main/src/Components/WebAssembly/Authentication.Msal/src/Interop/AuthenticationService.ts and adapt it to your needs.
@javiercn ,
The first option suggest to use Hybrid flow (using token response type) right ? Otherwise, since we have the authorization code on the WebAssembly, you suggest to request ourselves the access token ?
To clarify that, I guess that this should be the responsibility of the TokenProvider to do correctly the second option, right ?
@javiercn regarding your workaround suggestions:
You can likely avoid this issue if you request an access token for the app.
In a Blazor Web Assembly applicaton based on .NET 6.0.4 I try to request a access token like this and it throws a exception as mentioned by @syska
var accessTokenResult = await _tokenProvider.RequestAccessToken(); // <-- This throws exception
_tokenProvider is of type Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider
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.Serialization.Metadata.JsonPropertyInfo`1[[System.DateTimeOffset, System.Private.CoreLib, Version=6.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=6.0.4.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=6.0.4.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, AccessToken& value)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessToken, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.4.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=6.0.4.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=6.0.4.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=6.0.4.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=6.0.4.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=6.0.4.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.Read[Object](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo)
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__16`1[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.InternalAccessTokenResult, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.4.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=6.0.4.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteUserAccount, Microsoft.AspNetCore.Components.WebAssembly.Authentication, Version=6.0.4.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[Microsoft.Authentication.WebAssembly.Msal.Models.MsalProviderOptions, Microsoft.Authentication.WebAssembly.Msal, Version=6.0.4.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].MoveNext()
at SariDev.LetsEat.LetsEat.App.Shared.MainLayout.GetAllAsync() in C:\WS_Private\GitHub\SariDev\LetsEat\Code\Applications\LetsEat\LetsEat.App\Shared\MainLayout.razor:line 50
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at MudBlazor.MudBaseButton.OnClickHandler(MouseEventArgs ev)
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
Or do you mean to retrieve the access token in another way? Can you clarify that a bit?
Regarding
Alternatively you can provide your own JS based on https://github.com/dotnet/aspnetcore/blob/main/src/Components/WebAssembly/Authentication.Msal/src/Interop/AuthenticationService.ts and adapt it to your needs.
Has anyone here tried that and had success with it?
@SariDev unfortunately I didn't understand correctly what is expected to be the correct solution. The suggested workaround doesn't seem clear for me. Furthermore, I cannot understand why this issue is taking so much time since it's a blocking point for integrating Blazor WebAssembly with OpenID Connect...
@kbeaugrand same for me.
Maybe someone can clarify how those workarounds should be implemented with more details.
Furthermore, I cannot understand why this issue is taking so much time since it's a blocking point for integrating Blazor WebAssembly with OpenID Connect..
I'm also suprises by this. One would expect that this is a heavily requested Feature and that it should work without issues
@kbeaugrand here is a sample that shows how you can customize the JS we provide. It uses MSAL, but the steps are equivalent for OpenID Connect.
Looking at the sample:
interface AccessToken { value: string; expires: Date | null; grantedScopes: string[]; }
I presume from the error previously that the AccessToken has null expiry and thus cannot be converted to the DateTimeOffset by the serializer:
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.
Maybe it is line 164/165:
const result = await this.signInCore(request); if (!result) { return this.redirect(); } else if (this.isMsalError(result)) { return this.error(result.errorMessage); }
If the result contains something then it won't make the call on line 166. Not tried debugging it yet, thoughts?
Thanks for contacting us.
We're moving this issue to the .NET 7 Planning
milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
If it helps anyone here is how I implemented a work around for this.
I needed to get the token to pass it to my API.
I added this to the index.html
<script>
window.getJWT = () => JSON.parse(sessionStorage[
Object
.keys(sessionStorage)
.find(_ => _.includes("yourdomain.b2clogin.com-idtoken"))
])
.secret;
</script>
Then commented out the recommended message handler:
builder.Services.AddHttpClient(
"WebAPI",
(services,client) => {
client.BaseAddress = new Uri("http://localhost:7071");
}
);
// COMMENT THIS OUT
//.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
builder
.Services
.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
.CreateClient("WebAPI"));
Then when you use the Httpclient manually add it:
[Inject]
protected HttpClient? Http { get; set; }
[Inject]
protected IJSRuntime JS { get; set; }
protected override async Task OnInitializedAsync()
{
if (Http == null)
throw new ArgumentNullException(nameof(Http));
if (JS == null)
throw new ArgumentNullException(nameof(JS));
var text = await JS.InvokeAsync<string>("getJWT", new object[] { });
Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer",
text
);
using var stream = await Http.GetAsync("http://localhost:7071/api/Function1");
}
Its pretty janky but works for me until they roll out a fix :).
@Spaceman1861, this would add the id_token in the Authorization header, right ? In that case, I guess the authentication should not pass to the backend since this is not the access_token for your backend audience...
Perhaps I'm looking at it wrong @kbeaugrand ill walk you through the train of though if you think I have it wrong id love to know:
Passing the JWT as bearer from the session and then validating it in the function app allows with code like this.
public static async Task<JwtSecurityToken> ValidateAsync(string token)
{
string stsDiscoveryEndpoint = "https://YOURSITEHERE.b2clogin.com/YOURSITEHERE.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_Auth";
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
//1. need the 'new OpenIdConnect...'
OpenIdConnectConfiguration config = await configManager.GetConfigurationAsync();
TokenValidationParameters validationParameters = new TokenValidationParameters
{
//decode the JWT to see what these values should be
ValidAudience = "SOMEGUID", // Replaced values by XXXX
IssuerSigningKeys = config.SigningKeys, //2. .NET Core equivalent is "IssuerSigningKeys" and "SigningKeys"
ValidateIssuer = true,
ValidIssuer = "https://YOURSITEHERE.b2clogin.com/SOMEGUID/v2.0/",
ValidateAudience = true,
ValidateIssuerSigningKey = true,
RequireExpirationTime = true,
ValidateLifetime = true
};
JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();
SecurityToken jwt;
var result = tokendHandler.ValidateToken(token, validationParameters, out jwt);
return jwt as JwtSecurityToken;
}
@Spaceman1861
Can you print in the discussion, the tokens you have in the session storage (not the values, just the keys) ? Maybe I miss understand the OAuth 2.0 (and OpenId protocol), but with the AspNetCore Assembly, I can only work with the id_token. To my standing point, my WebAssembly App should be considered as a client app, and should act to my API on behalf of the user. So my API refuse the id_token as the Bearer token because it has been issued for identification, not for authorization....
Source: https://auth0.com/blog/id-token-access-token-what-is-the-difference/.
@javiercn, I cannot understand the decision to move the fix to this issue to .NET 7. What is the solution to use WebAssembly Authenticated (even in MSAL or OpenIdConnect) and provide the access token to the API part properly ?
I have two issues :
$.token.expires
issueThese two issues makes the Blazor WebAssembly not usable with an authenticated resource !
This issue has been moved from a ticket on Developer Community.
I have created a Blazor application and I use Msal to do authentication following the examples from Azure B2C. With my B2C configuration in the server, I can successfully login, I get the User, the claims and I can call the api. I would need to have access to the token during development to be able to use that token to call my api services directly using swagger. So during Debugging I wanted to print the token on screen to copy and paste.
However, when I try to get the token in the Client after successful login, I get an Exception:
An exception occurred executing JS interop: The JSON value could not be converted to System.DateTimeOffset. Path: $.token.expires
This is a very confusing exception and doesn't seem to explain the type of error that is occurring. It seems that is not doing any validation during the parsing or pre-parsing. So not sure why this is happening.
More details:
I initialise with this:
I also use a custom AuthorizationMessageHandler to be able to call the api, which works well.
However, when in my code I call the code to retrieve the Token, I get the exception + one unhandled exception:
And additionally there is an unhandled exception:
I have tried in B2C to set the configuration, and I'm able to run the SignIn flow redirecting to jwt.ms passing the token and decoding it.
And I get the token decoded when redirecting directly to jwt.ms:
Original Comments
Feedback Bot on 11/12/2021, 00:15 AM:
We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.
Original Solutions
(no solutions)