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

Newtonsoft can't deserialize user response #716

Open
5 tasks done
BrandonBoone opened this issue Jun 1, 2024 · 2 comments
Open
5 tasks done

Newtonsoft can't deserialize user response #716

BrandonBoone opened this issue Jun 1, 2024 · 2 comments
Assignees
Labels
bug This points to a verified bug in the code

Comments

@BrandonBoone
Copy link

BrandonBoone commented Jun 1, 2024

Checklist

  • I have looked into the Readme and have not found a suitable solution or answer.
  • I have looked into the API documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have searched the Auth0 Community forums and have not found a suitable solution or answer.
  • I agree to the terms within the Auth0 Code of Conduct.

Description

The Auth0 SDK cannot desterilize the JSON response from the following API call:

API Call: https://dev-nextech.us.auth0.com/api/v2/users?q=identities.connection%3A%22Username-Password-Authentication%22%20AND%20email%3A%22b.boone%40mailinator.com%22&search_engine=v3

Response:

[
  {
    "email": "[email protected]",
    "email_verified": true,
    "blocked": false,
    "created_at": "2023-06-20T16:24:03.232Z",
    "updated_at": "2024-05-31T18:56:09.778Z",
    "identities": [
      {
        "connection": "Username-Password-Authentication",
        "provider": "auth0",
        "user_id": "6491d2d0088e46b72de20b35",
        "isSocial": false
      }
    ],
    "user_id": "auth0|6491d2d0088e46b72de20b35",
    "name": "[email protected]",
    "picture": "https://secure.gravatar.com/avatar/ef417adb54a7e4db7773f3d434919711?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fb.png",
    "nickname": "b.boone",
    "last_password_reset": "2024-01-22T17:17:35.911Z",
    "user_metadata": {

    },
    "multifactor": [
      "guardian",
      [
        "otp",
        "sms",
        "email",
        "push"
      ]
    ],
    "multifactor_last_modified": "2024-05-31T18:50:13.044Z",
    "last_login": "2024-05-31T18:48:57.480Z",
    "last_ip": "47.206.147.48",
    "logins_count": 118,
    "app_metadata": {

    }
  }
]

Specifically, Newtonsoft Json cannot deserialize the following portion:

"multifactor": [
      "guardian",
      [
        "otp",
        "sms",
        "email",
        "push"
      ]
    ],

Example usage

public async Task<IPagedList<User>> GetUsersByEmailAddressAsync(string emailAddress)
=> await (
    await _managementApiClientFactory.CreateAsync()
).Users.GetAllAsync(new GetUsersRequest()
{
    Query = $"identities.connection:\"{CONNECTION_ID}\" AND email:\"{emailAddress}\"",
    SearchEngine = "v3"
});

Stack Trace:

Newtonsoft.Json.JsonReaderException: Error reading string. Unexpected token: StartArray. Path '[0].multifactor[1]', line 1, position 711.
   at Newtonsoft.Json.JsonReader.ReadAsString()
   at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
   at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType)
   at Newtonsoft.Json.Linq.JToken.ToObject[T]()
   at Auth0.ManagementApi.Paging.PagedListConverter`1.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Auth0.ManagementApi.HttpClientManagementConnection.SendRequest[T](HttpRequestMessage request, JsonConverter[] converters, CancellationToken cancellationToken)
   at Auth0.ManagementApi.HttpClientManagementConnection.GetAsyncInternal[T](Uri uri, IDictionary`2 headers, JsonConverter[] converters, CancellationToken cancellationToken)
   at Auth0.ManagementApi.HttpClientManagementConnection.<>c__DisplayClass13_0`1.<<GetAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Auth0.ManagementApi.HttpClientManagementConnection.Retry[TResult](Func`1 retryable)
   at Auth0.ManagementApi.HttpClientManagementConnection.GetAsync[T](Uri uri, IDictionary`2 headers, JsonConverter[] converters, CancellationToken cancellationToken)
   at nextech_auth0_shared.Services.Auth0ManagementService.GetUsersByEmailAddressAsync(String emailAddress) in C:\....\UserController.cs:line 125
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Nextech.Api.ResponseCache.ApiResponseCacheMiddleware.InvokeAsync(HttpContext context, IApiResponseCacheClient cache)
   at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

According to the Managemen API documentation, multifactor should be a list of string: [] and should not contain a nested array.

image

Reproduction

We traced the cause to our implementation of MFA in a onExecutePostLogin flow.

The call to enable MFA temporarily had the incorrect values:

api.multifactor.enable([
"otp",
"sms",
"email",
"push"
], {
      allowRememberBrowser: false,
});

And was changed to:

api.multifactor.enable('any', {
      allowRememberBrowser: false,
});

It seems the api.multifactor.enable method is not validating the parameters sent to it.

Additional context

No response

auth0.net version

7.26.2

.NET version

6

@BrandonBoone BrandonBoone added the bug This points to a verified bug in the code label Jun 1, 2024
@kailash-b
Copy link
Contributor

Hi @BrandonBoone
Thanks for reaching out.

According to the Management API docs "multifactor" is indeed just a list of strings and we do not expect it to be otherwise.. The Auth0 SDK does handle when the "multifactor" is a list of strings.

We are not able to reproduce a response where the "multifactor" is not a list of strings (but a nested list as shown above).
Can you confirm if you are still seeing this behaviour / Or help us with how we can reproduce this to assist better?

@BrandonBoone
Copy link
Author

You would be able to reproduce in the onExecutePostLogin as described above, by passing in erroneous data to the api.multifactor.enable method. If in your testing, the method (and underlying API) no longer accepts erroneous values, then this is likely resolved (see https://support.auth0.com/tickets/02352938 if you have access). I do not wish to test it myself in my own environments as the erronous users are unrecoverable without a ticket to Auth0.

@kailash-b kailash-b self-assigned this Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This points to a verified bug in the code
Projects
None yet
Development

No branches or pull requests

2 participants