Newtonsoft can't deserialize user response
Checklist
- [X] I have looked into the Readme and have not found a suitable solution or answer.
- [X] I have looked into the API documentation and have not found a suitable solution or answer.
- [X] I have searched the issues and have not found a suitable solution or answer.
- [X] I have searched the Auth0 Community forums and have not found a suitable solution or answer.
- [X] 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.
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