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

[Bug] The JSON value could not be converted to System.Int64. ROPC flow #3892

Closed
1 of 7 tasks
dmitriyi-affinity opened this issue Jan 9, 2023 · 11 comments
Closed
1 of 7 tasks

Comments

@dmitriyi-affinity
Copy link

dmitriyi-affinity commented Jan 9, 2023

Logs and network traces

System.Text.Json.JsonException
The JSON value could not be converted to System.Int64. Path: $.expires_in | LineNumber: 0 | BytePositionInLine: 1332.
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCoreAsObject(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Deserialize(String json, Type returnType, JsonSerializerContext context)
   at Microsoft.Identity.Client.Utils.JsonHelper.DeserializeFromJson[T](String json)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.CreateResponse[T](HttpResponse response, RequestContext requestContext)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.ExecuteRequestAsync[T](Uri endPoint, HttpMethod method, RequestContext requestContext, Boolean expectErrorsOn200OK, Boolean addCommonHeaders, Func`2 onBeforePostRequestData)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.GetTokenAsync(Uri endPoint, RequestContext requestContext, Boolean addCommonHeaders, Func`2 onBeforePostRequestHandler)
   at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint, ILoggerAdapter logger)
   at Microsoft.Identity.Client.OAuth2.TokenClient.SendTokenRequestAsync(IDictionary`2 additionalBodyParameters, String scopeOverride, String tokenEndpointOverride, CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.UsernamePasswordRequest.GetTokenResponseAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.UsernamePasswordRequest.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.ApiConfig.Executors.PublicClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenByUsernamePasswordParameters usernamePasswordParameters, CancellationToken cancellationToken)

Which version of MSAL.NET are you using?
MSAL.NET 4.49.x, 4.48.x - Problem
Works in 4.47.2 - No Issues

Platform
.Net 7.0, .Net 6.0 (.Net 4.8 not tested)

What authentication flow has the issue?

  • Desktop / Mobile
    • Interactive
    • Integrated Windows Authentication
    • Username Password
    • Device code flow (browserless)
  • Web app
    • Authorization code
    • On-Behalf-Of
  • Daemon app
    • Service to Service calls

Other?

Is this a new or existing app?
a. The app is in production, and I have upgraded to a new version of MSAL.
-->

Repro

                    var publicClientBuilder = PublicClientApplicationBuilder.CreateWithApplicationOptions(options);
                    publicClientBuilder.WithB2CAuthority('MY AUTHORITY');
                    var publicClient = publicClientBuilder.Build();
                    
                    // Gives exception only after upgrade to 4.48+
                    var result = await publicClient.AcquireTokenByUsernamePassword(
                            new string[]{'MyScopes1', 'MyScope2'},
                            'MyUserName',
                            password)
                        .ExecuteAsync().ConfigureAwait(false);

Some guess about the issue:
image

Probably something went wrong when STJ deseriailzer Source Generator ignored the settings that are defined here:
image

Azure AD B2C returns expires_in field as a string :(
https://learn.microsoft.com/en-us/answers/questions/877384/azure-active-directory-b2c-authorization-code-flow.html

@dmitriyi-affinity dmitriyi-affinity changed the title [Bug] [Bug] The JSON value could not be converted to System.Int64. ROCP flow Jan 9, 2023
@dmitriyi-affinity dmitriyi-affinity changed the title [Bug] The JSON value could not be converted to System.Int64. ROCP flow [Bug] The JSON value could not be converted to System.Int64. ROPC flow Jan 9, 2023
@pmaytak pmaytak added this to the 4.50.0 milestone Jan 10, 2023
@trwalke trwalke self-assigned this Jan 10, 2023
@bgavrilMS
Copy link
Member

Would be nice to have an E2E test with B2C + ROPC, even if we have to hardcode client id etc.

@bgavrilMS
Copy link
Member

Based on the question shared by @dmitriyi-affinity, all token responses from B2C suffer from this, not just ROPC. So this affects B2C + desktop apps.

@mgroetan
Copy link

Can confirm that this also affects "Interactive" flow as well:

System.Text.Json.JsonException
  HResult=0x80131500
  Message=The JSON value could not be converted to System.Int64. Path: $.expires_in | LineNumber: 0 | BytePositionInLine: 2821.
  Source=System.Text.Json
  StackTrace:
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCoreAsObject(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Deserialize(String json, Type returnType, JsonSerializerContext context)
   at Microsoft.Identity.Client.Utils.JsonHelper.DeserializeFromJson[T](String json)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.CreateResponse[T](HttpResponse response, RequestContext requestContext)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.<ExecuteRequestAsync>d__11`1.MoveNext()
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.<GetTokenAsync>d__10.MoveNext()
   at Microsoft.Identity.Client.OAuth2.TokenClient.<SendHttpAndClearTelemetryAsync>d__11.MoveNext()
   at Microsoft.Identity.Client.OAuth2.TokenClient.<SendTokenRequestAsync>d__5.MoveNext()
   at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.<GetTokenResponseAsync>d__11.MoveNext()
   at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest.<ExecuteAsync>d__9.MoveNext()
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__12.MoveNext()
   at Microsoft.Identity.Client.ApiConfig.Executors.PublicClientExecutor.<ExecuteAsync>d__2.MoveNext()

This works even with the latest 4.49.1 version, when targeting .NET Framework (4.7.2).
For any .NET 6/7 usage it fails.

Have further investigated that it has to do with the "System.Text.Json" package itself.
When this was updated from 6.0.7 to 7.0.1, it starts failing.

@bgavrilMS
Copy link
Member

This System.Text.Json behavior was not documeted as a breaking change https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-7/#breaking-changes

Note that we've only started using System.Text.Json since MSAL 4.47.0 (roughly). If you use 4.46 it should be ok.

@pmaytak
Copy link
Contributor

pmaytak commented Jan 12, 2023

@mgroetan

  • So if your app targets .NET 7 and uses 6.0.7 package, it works?
  • What if you target .NET 7 and not explicitly use System.Text.Json package?

@trwalke Can you also test above, since targeting 6.0.7 may be a temporary work around until the fix.

@trwalke
Copy link
Member

trwalke commented Jan 12, 2023

I can confirm with my testing that targeting .NET 7 causes this issue. Targeting .NET 6 seems to resolve it with the latest version of MSAL so targeting 6.0.7 seems to be a temporary work around

@trwalke
Copy link
Member

trwalke commented Jan 13, 2023

Found a potential solution.
So there are two ways to set serialization/deserialization behavior in System.Test.Json (there may be others)

  • JsonSerializerContext
  • JsonSerializerOptions.

It seems like tergetting .NET 7 causes the
object? Deserialize(string json, Type returnType, JsonSerializerContext context) api to ignore the configuration in the JsonSerializerContext.

However, using object? Deserialize(string json, Type returnType, JsonSerializerOptions? options = null) and setting JsonSerializerOptions seems to work.

@trwalke
Copy link
Member

trwalke commented Jan 13, 2023

opened bug on .NET 7 repo
dotnet/runtime#80634

@a-dovgal
Copy link

opened bug on .NET 7 repo
dotnet/runtime#80634

Hello!
How about .NET 6? Actually, that bug also exists in the current latest stable version, 4.49.1. But as mentioned before, it works in Microsoft.Identity.Client 4.47.2
Are you going to fix it?

@bgavrilMS
Copy link
Member

I'll let @trwalke clarify, but I think we'll fix it separately from .NET folks - there is a PR in progress. We'll probably have a release with the fix in 1-2 weeks. If this blocking you, we can accelerate, but I assume you can use MSAL 4.47.2 for now?

@trwalke
Copy link
Member

trwalke commented Feb 2, 2023

We have a workaround that resolves this issue for us. The .NET 7 team will continue to resolve the root cause on their side but at least we have a solution for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests

6 participants