From 0984c6d784fd0d34d7416a53191af0f7ef5ea92c Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Thu, 1 Apr 2021 00:12:55 +0100 Subject: [PATCH] Do not serialize Parameters property on AuthenticationProperties (#31414) * Do not serialize Parameters Explicitly prevent the Parameters dictionary from being included in the deserialized payload. See https://github.com/dotnet/aspnetcore/pull/31330#discussion_r605078290. * Ignore props backed by Items Also ignore the properties backed by the Items dictionary to minimise the size of the serialized JSON payload. * Add ignoreLineEndingDifferences Stop tests from failing on non-Windows OSs due to different line endings. --- .../src/AuthenticationProperties.cs | 6 +++ .../test/AuthenticationPropertiesTests.cs | 50 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/Http/Authentication.Abstractions/src/AuthenticationProperties.cs b/src/Http/Authentication.Abstractions/src/AuthenticationProperties.cs index 3a72df17bda8..383ace3de04c 100644 --- a/src/Http/Authentication.Abstractions/src/AuthenticationProperties.cs +++ b/src/Http/Authentication.Abstractions/src/AuthenticationProperties.cs @@ -65,11 +65,13 @@ public AuthenticationProperties Clone() /// Collection of parameters that are passed to the authentication handler. These are not intended for /// serialization or persistence, only for flowing data between call sites. /// + [JsonIgnore] public IDictionary Parameters { get; } /// /// Gets or sets whether the authentication session is persisted across multiple requests. /// + [JsonIgnore] public bool IsPersistent { get => GetString(IsPersistentKey) != null; @@ -79,6 +81,7 @@ public bool IsPersistent /// /// Gets or sets the full path or absolute URI to be used as an http redirect response value. /// + [JsonIgnore] public string? RedirectUri { get => GetString(RedirectUriKey); @@ -88,6 +91,7 @@ public string? RedirectUri /// /// Gets or sets the time at which the authentication ticket was issued. /// + [JsonIgnore] public DateTimeOffset? IssuedUtc { get => GetDateTimeOffset(IssuedUtcKey); @@ -97,6 +101,7 @@ public DateTimeOffset? IssuedUtc /// /// Gets or sets the time at which the authentication ticket expires. /// + [JsonIgnore] public DateTimeOffset? ExpiresUtc { get => GetDateTimeOffset(ExpiresUtcKey); @@ -106,6 +111,7 @@ public DateTimeOffset? ExpiresUtc /// /// Gets or sets if refreshing the authentication session should be allowed. /// + [JsonIgnore] public bool? AllowRefresh { get => GetBool(RefreshKey); diff --git a/src/Http/Authentication.Core/test/AuthenticationPropertiesTests.cs b/src/Http/Authentication.Core/test/AuthenticationPropertiesTests.cs index e486ce3255a7..f69c988fd362 100644 --- a/src/Http/Authentication.Core/test/AuthenticationPropertiesTests.cs +++ b/src/Http/Authentication.Core/test/AuthenticationPropertiesTests.cs @@ -320,6 +320,12 @@ public void Roundtrip_Serializes_With_SystemTextJson() props.Parameters.Add("baz", "quux"); var json = JsonSerializer.Serialize(props); + + // Verify that Parameters was not serialized + Assert.NotNull(json); + Assert.DoesNotContain("baz", json); + Assert.DoesNotContain("quux", json); + var deserialized = JsonSerializer.Deserialize(json); Assert.NotNull(deserialized); @@ -339,6 +345,50 @@ public void Roundtrip_Serializes_With_SystemTextJson() Assert.Equal(0, deserialized.Parameters.Count); } + [Fact] + public void Parameters_Is_Not_Deserialized_With_SystemTextJson() + { + var json = @"{""Parameters"":{""baz"":""quux""}}"; + + var deserialized = JsonSerializer.Deserialize(json); + + Assert.NotNull(deserialized); + + // Ensure that parameters is not deserialized from a raw payload + Assert.NotNull(deserialized!.Parameters); + Assert.Equal(0, deserialized.Parameters.Count); + } + + [Fact] + public void Serialization_Is_Minimised_With_SystemTextJson() + { + var props = new AuthenticationProperties() + { + AllowRefresh = true, + ExpiresUtc = new DateTimeOffset(2021, 03, 28, 13, 47, 00, TimeSpan.Zero), + IssuedUtc = new DateTimeOffset(2021, 03, 28, 12, 47, 00, TimeSpan.Zero), + IsPersistent = true, + RedirectUri = "/foo/bar" + }; + + props.Items.Add("foo", "bar"); + + var options = new JsonSerializerOptions() { WriteIndented = true }; // Indented for readability if test fails + var json = JsonSerializer.Serialize(props, options); + + // Verify that the payload doesn't duplicate the properties backed by Items + Assert.Equal(@"{ + ""Items"": { + "".refresh"": ""True"", + "".expires"": ""Sun, 28 Mar 2021 13:47:00 GMT"", + "".issued"": ""Sun, 28 Mar 2021 12:47:00 GMT"", + "".persistent"": """", + "".redirect"": ""/foo/bar"", + ""foo"": ""bar"" + } +}", json, ignoreLineEndingDifferences: true); + } + public class MyAuthenticationProperties : AuthenticationProperties { public new DateTimeOffset? GetDateTimeOffset(string key)