Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 27 additions & 35 deletions src/Auth0.AuthenticationApi/FlexibleDateTimeConverter.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,43 @@
using System;

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Auth0.AuthenticationApi;

/// <summary>
/// A JSON date converter that reads both ISO 8601 and epoch dates.
/// A JSON date converter that reads both ISO 8601 and epoch (seconds) dates.
/// </summary>
internal class FlexibleDateTimeConverter : IsoDateTimeConverter
internal class FlexibleDateTimeConverter : JsonConverter<DateTime?>
{
private static readonly DateTime Epoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
switch (reader.TokenType)
{
case JsonTokenType.Null:
return null;
case JsonTokenType.Number:
return Add(Epoch, TimeSpan.FromSeconds(reader.GetInt64()));
case JsonTokenType.String:
// Prefer STJ's ISO 8601 reader; fall back to a lenient parse for other
// formats. An unparseable value yields null rather than throwing and
// failing the entire enclosing object's deserialization.
if (reader.TryGetDateTime(out var iso))
return iso;
return DateTime.TryParse(reader.GetString(), CultureInfo.InvariantCulture,
DateTimeStyles.RoundtripKind, out var parsed) ? parsed : null;
default:
return null;
}
}

public override bool CanWrite => false;

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)
{
if (reader.Value == null) return null;

return reader.TokenType == JsonToken.Integer
? Add(Epoch, TimeSpan.FromSeconds((long)reader.Value))
: reader.Value;
throw new NotImplementedException();
}

/// <summary>
/// Add a DateTime and a TimeSpan.
/// The maximum time is DateTime.MaxTime. It is not an error if time + timespan > MaxTime.
/// Just return MaxTime.
/// </summary>
/// <param name="time">Initial <see cref="DateTime"/> value.</param>
/// <param name="timespan"><see cref="TimeSpan"/> to add.</param>
/// <returns><see cref="DateTime"/> as the sum of time and timespan.</returns>
private static DateTime Add(DateTime time, TimeSpan timespan)
{
if (timespan == TimeSpan.Zero)
Expand All @@ -50,25 +52,15 @@ private static DateTime Add(DateTime time, TimeSpan timespan)
return time + timespan;
}

/// <summary>
/// Gets the Maximum value for a DateTime specifying kind.
/// </summary>
/// <param name="kind">DateTimeKind to use.</param>
/// <returns>DateTime of specified kind.</returns>
private static DateTime GetMaxValue(DateTimeKind kind)
{
return new DateTime(DateTime.MaxValue.Ticks,
kind == DateTimeKind.Unspecified ? DateTimeKind.Utc : kind);
}

/// <summary>
/// Gets the Minimum value for a DateTime specifying kind.
/// </summary>
/// <param name="kind">DateTimeKind to use.</param>
/// <returns>DateTime of specified kind.</returns>
private static DateTime GetMinValue(DateTimeKind kind)
{
return new DateTime(DateTime.MinValue.Ticks,
kind == DateTimeKind.Unspecified ? DateTimeKind.Utc : kind);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
using System.Threading;
using System.Threading.Tasks;

using Newtonsoft.Json;
using System.Text.Json;
using Auth0.Core.Serialization;

using Auth0.Core.Exceptions;
using Auth0.Core.Http;
Expand All @@ -20,8 +21,6 @@
/// </summary>
public class HttpClientAuthenticationConnection : IAuthenticationConnection, IDisposable
{
private static readonly JsonSerializerSettings jsonSerializerSettings = new() { NullValueHandling = NullValueHandling.Ignore, DateParseHandling = DateParseHandling.DateTime };

private readonly HttpClient httpClient;
private readonly string agentString;
private bool ownHttpClient;
Expand All @@ -36,7 +35,7 @@
/// If you do not supply a <see cref="HttpClient"/> one will be created automatically and disposed
/// of when this object is disposed.
/// </remarks>
public HttpClientAuthenticationConnection(HttpClient httpClient = null)

Check warning on line 38 in src/Auth0.AuthenticationApi/HttpClientAuthenticationConnection.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.

Check warning on line 38 in src/Auth0.AuthenticationApi/HttpClientAuthenticationConnection.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.
{
ownHttpClient = httpClient == null;
this.httpClient = httpClient ?? new HttpClient();
Expand All @@ -58,7 +57,7 @@
}

/// <inheritdoc/>
public async Task<T> GetAsync<T>(Uri uri, IDictionary<string, string> headers = null, CancellationToken cancellationToken = default)

Check warning on line 60 in src/Auth0.AuthenticationApi/HttpClientAuthenticationConnection.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.

Check warning on line 60 in src/Auth0.AuthenticationApi/HttpClientAuthenticationConnection.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.
{
using (var request = new HttpRequestMessage(HttpMethod.Get, uri))
{
Expand All @@ -68,7 +67,7 @@
}

/// <inheritdoc/>
public async Task<T> SendAsync<T>(HttpMethod method, Uri uri, object body, IDictionary<string, string> headers = null, CancellationToken cancellationToken = default)

Check warning on line 70 in src/Auth0.AuthenticationApi/HttpClientAuthenticationConnection.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.
{
using (var request = new HttpRequestMessage(method, uri) { Content = BuildMessageContent(body) })
{
Expand Down Expand Up @@ -98,9 +97,13 @@

internal T DeserializeContent<T>(string content)
{
return typeof(T) == typeof(string)
? (T)(object)content
: JsonConvert.DeserializeObject<T>(content, jsonSerializerSettings);
if (typeof(T) == typeof(string))
return (T)(object)content;

if (string.IsNullOrWhiteSpace(content))
return default;

return JsonSerializer.Deserialize<T>(content, Auth0JsonSerializerOptions.Default);
}

private void ApplyHeaders(HttpRequestMessage request, IDictionary<string, string> headers)
Expand All @@ -125,7 +128,7 @@

private static HttpContent CreateJsonStringContent(object body)
{
var json = JsonConvert.SerializeObject(body, jsonSerializerSettings);
var json = JsonSerializer.Serialize(body, body.GetType(), Auth0JsonSerializerOptions.Default);
return new StringContent(json, Encoding.UTF8, "application/json");
}

Expand Down Expand Up @@ -157,12 +160,12 @@
#endif

var sdkVersion = typeof(HttpClientAuthenticationConnection).GetTypeInfo().Assembly.GetName().Version;
var agentJson = JsonConvert.SerializeObject(new
var agentJson = JsonSerializer.Serialize(new
{
name = "Auth0.Net",
version = sdkVersion.Major + "." + sdkVersion.Minor + "." + sdkVersion.Revision,
env = new { target }
}, Formatting.None);
});
return Utils.Base64UrlEncode(Encoding.UTF8.GetBytes(agentJson));
}

Expand Down
8 changes: 4 additions & 4 deletions src/Auth0.AuthenticationApi/Models/AccessTokenResponse.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace Auth0.AuthenticationApi.Models;

Expand All @@ -11,19 +11,19 @@ public class AccessTokenResponse : TokenBase
/// <summary>
/// Identifier token.
/// </summary>
[JsonProperty("id_token")]
[JsonPropertyName("id_token")]
public string IdToken { get; set; }

/// <summary>
/// Expiration time in seconds.
/// </summary>
[JsonProperty("expires_in")]
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }

/// <summary>
/// Refresh token.
/// </summary>
[JsonProperty("refresh_token")]
[JsonPropertyName("refresh_token")]
public string RefreshToken { get; set; }

public IDictionary<string, IEnumerable<string>> Headers { get; set; }
Expand Down
4 changes: 2 additions & 2 deletions src/Auth0.AuthenticationApi/Models/ChangePasswordRequest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace Auth0.AuthenticationApi.Models;

Expand All @@ -10,6 +10,6 @@ public class ChangePasswordRequest : UserMaintenanceRequestBase
/// <summary>
/// The organization_id of the Organization associated with the user.
/// </summary>
[JsonProperty("organization")]
[JsonPropertyName("organization")]
public string Organization { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace Auth0.AuthenticationApi.Models.Ciba;

Expand All @@ -10,18 +10,18 @@ public class ClientInitiatedBackchannelAuthorizationResponse
/// <summary>
/// Unique id of the authorization request. Can be used further to poll for /oauth/token.
/// </summary>
[JsonProperty("auth_req_id")]
[JsonPropertyName("auth_req_id")]
public string AuthRequestId { get; set; }

/// <summary>
/// Tells you how many seconds we have until the authentication request expires.
/// </summary>
[JsonProperty("expires_in")]
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }

/// <summary>
/// Tells how many seconds you must leave between poll requests.
/// </summary>
[JsonProperty("interval")]
[JsonPropertyName("interval")]
public int Interval { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;

using Newtonsoft.Json;
using System.Text.Json;
using System.Text.Json.Serialization;

using Auth0.AuthenticationApi.Models;
using Auth0.Core.Serialization;
Expand All @@ -10,25 +10,25 @@ namespace Auth0.AuthenticationApi.Models.Ciba;

public class ClientInitiatedBackchannelAuthorizationTokenResponse : AccessTokenResponse
{
[JsonProperty("scope")]
[JsonPropertyName("scope")]
public string Scope { get; set; }

/// <summary>
/// Raw <c>authorization_details</c> JSON returned by the token endpoint as part of a
/// Rich Authorization Requests (RAR) flow. Use <see cref="AuthorizationDetails"/> for a strongly-typed view.
/// </summary>
[JsonProperty("authorization_details")]
[JsonPropertyName("authorization_details")]
[JsonConverter(typeof(StringOrObjectAsStringConverter))]
public string AuthorizationDetailsRaw { get; set; }

private bool _authorizationDetailsParsed;
private IReadOnlyList<AuthorizationDetail> _authorizationDetails;

/// <summary>
/// Strongly-typed view of the <c>authorization_details</c> returned by the token endpoint.
/// Returns <see langword="null"/> when no authorization details were returned.
/// </summary>
private bool _authorizationDetailsParsed;
private IReadOnlyList<AuthorizationDetail> _authorizationDetails;

[Newtonsoft.Json.JsonIgnore]
[JsonIgnore]
public IReadOnlyList<AuthorizationDetail> AuthorizationDetails
{
get
Expand All @@ -41,11 +41,11 @@ public IReadOnlyList<AuthorizationDetail> AuthorizationDetails

try
{
_authorizationDetails = System.Text.Json.JsonSerializer.Deserialize<IReadOnlyList<AuthorizationDetail>>(AuthorizationDetailsRaw);
_authorizationDetails = JsonSerializer.Deserialize<IReadOnlyList<AuthorizationDetail>>(AuthorizationDetailsRaw);
_authorizationDetailsParsed = true;
return _authorizationDetails;
}
catch (System.Text.Json.JsonException ex)
catch (JsonException ex)
{
throw new InvalidOperationException(
"Failed to deserialize the 'authorization_details' returned by the token endpoint.", ex);
Expand Down
19 changes: 10 additions & 9 deletions src/Auth0.AuthenticationApi/Models/Ciba/LoginHint.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Auth0.AuthenticationApi.Models.Ciba;

Expand All @@ -7,21 +8,21 @@ namespace Auth0.AuthenticationApi.Models.Ciba;
/// </summary>
public class LoginHint
{
[JsonProperty("format")]
[JsonPropertyName("format")]
public string Format { get; set; }

/// <summary>
/// Issuer of the ID Token.
/// Issuer of the ID Token.
/// This value should match the 'Issuer' value configured in the well-known configuration.
/// </summary>
[JsonProperty("iss")]
[JsonPropertyName("iss")]
public string Issuer { get; set; }
[JsonProperty("sub")]

[JsonPropertyName("sub")]
public string Subject { get; set; }

public override string ToString()
{
return JsonConvert.SerializeObject(this);
return JsonSerializer.Serialize(this, Auth0.Core.Serialization.Auth0JsonSerializerOptions.Default);
}
}
}
14 changes: 7 additions & 7 deletions src/Auth0.AuthenticationApi/Models/DeviceCodeResponse.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace Auth0.AuthenticationApi.Models;

Expand All @@ -10,36 +10,36 @@ public class DeviceCodeResponse
/// <summary>
/// The unique code for the device. When the user goes to the <see cref="VerificationUri"/> in their browser-based device, this code will be bound to their session.
/// </summary>
[JsonProperty("device_code")]
[JsonPropertyName("device_code")]
public string DeviceCode { get; set; }

/// <summary>
/// The code that should be input at the <see cref="VerificationUri"/> to authorize the device.
/// </summary>
[JsonProperty("user_code")]
[JsonPropertyName("user_code")]
public string UserCode { get; set; }

/// <summary>
/// The URL the user should visit to authorize the device.
/// </summary>
[JsonProperty("verification_uri")]
[JsonPropertyName("verification_uri")]
public string VerificationUri { get; set; }

/// <summary>
/// The lifetime (in seconds) of the <see cref="DeviceCode"/> and <see cref="UserCode"/>.
/// </summary>
[JsonProperty("expires_in")]
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }

/// <summary>
/// The interval (in seconds) at which the app should poll the token URL to request a token.
/// </summary>
[JsonProperty("interval")]
[JsonPropertyName("interval")]
public int Interval { get; set; }

/// <summary>
/// The complete URL the user should visit to authorize the device. This allows embedding the <see cref="UserCode"/> in the URL.
/// </summary>
[JsonProperty("verification_uri_complete")]
[JsonPropertyName("verification_uri_complete")]
public string VerificationUriComplete { get; set; }
}
Loading
Loading