From 323dda347889c3998cb08ef86f6c9c75d2eaf4a4 Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Fri, 12 Jul 2024 15:56:29 -0700 Subject: [PATCH] Additional Write API take a Stream (#2698) * new api takes stream * rename method * remove usings * void when takes a stream, comment strings * add testing, add api to public namespace * review feedback --- .../OpenIdConnectConfiguration.cs | 24 ++++++- .../OpenIdConnectConfigurationSerializer.cs | 14 +++++ .../OpenIdConnectConfigurationTests.cs | 63 +++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs index 892dde5e5a..6ff1c65483 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; +using System.IO; using System.Text.Json.Serialization; using System.Threading; using Microsoft.IdentityModel.Abstractions; @@ -81,7 +82,7 @@ public static OpenIdConnectConfiguration Create(string json) /// /// object to serialize. /// json string representing the configuration object. - /// Thrown if is null. + /// Thrown if is . public static string Write(OpenIdConnectConfiguration configuration) { if (configuration == null) @@ -93,6 +94,27 @@ public static string Write(OpenIdConnectConfiguration configuration) return OpenIdConnectConfigurationSerializer.Write(configuration); } + /// + /// Writes an as JSON to the . + /// + /// The to serialize. + /// The to write to. + /// Because a is provided, this method does not return a value. + /// Thrown if or is . + public static void Write(OpenIdConnectConfiguration configuration, Stream stream) + { + if (configuration == null) + throw LogHelper.LogArgumentNullException(nameof(configuration)); + + if (stream == null) + throw LogHelper.LogArgumentNullException(nameof(stream)); + + if (LogHelper.IsEnabled(EventLogLevel.Verbose)) + LogHelper.LogVerbose(LogMessages.IDX21809); + + OpenIdConnectConfigurationSerializer.Write(configuration, stream); + } + /// /// Initializes an new instance of . /// diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs index 33f5308f9a..6fa2a9bd8c 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs @@ -617,6 +617,20 @@ public static string Write(OpenIdConnectConfiguration OpenIdConnectConfiguration } } + public static void Write(OpenIdConnectConfiguration OpenIdConnectConfiguration, Stream stream) + { + Utf8JsonWriter writer = null; + try + { + writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); + Write(ref writer, OpenIdConnectConfiguration); + } + finally + { + writer?.Dispose(); + } + } + public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration config) { writer.WriteStartObject(); diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs index 5437bface4..87ddf99d3e 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs @@ -5,7 +5,10 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; +using System.IO; using System.Reflection; +using System.Security.Cryptography; +using System.Text; using System.Text.Json; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens; @@ -276,6 +279,32 @@ public void RoundTripFromJson() TestUtilities.AssertFailIfErrors(context); } + [Fact] + public void RoundTripFromJsonWithStream() + { + using MemoryStream stream = new(); + + var context = new CompareContext { Title = "RoundTripFromJson" }; + var oidcConfig1 = OpenIdConnectConfiguration.Create(OpenIdConfigData.JsonAllValues); + var oidcConfig2 = new OpenIdConnectConfiguration(OpenIdConfigData.JsonAllValues); + + OpenIdConnectConfiguration.Write(oidcConfig1, stream); + var oidcJson1 = Encoding.UTF8.GetString(stream.ToArray()); + var oidcConfig3 = OpenIdConnectConfiguration.Create(oidcJson1); + stream.SetLength(0); + + OpenIdConnectConfiguration.Write(oidcConfig2, stream); + var oidcJson2 = Encoding.UTF8.GetString(stream.ToArray()); + var oidcConfig4 = new OpenIdConnectConfiguration(oidcJson2); + + IdentityComparer.AreEqual(oidcConfig1, oidcConfig2, context); + IdentityComparer.AreEqual(oidcConfig1, oidcConfig3, context); + IdentityComparer.AreEqual(oidcConfig1, oidcConfig4, context); + IdentityComparer.AreEqual(oidcJson1, oidcJson2, context); + + TestUtilities.AssertFailIfErrors(context); + } + [Fact] public void EmptyCollectionSerialization() { @@ -289,6 +318,22 @@ public void EmptyCollectionSerialization() TestUtilities.AssertFailIfErrors(context); } + [Fact] + public void EmptyCollectionSerializationWithStream() + { + using MemoryStream stream = new(); + + var context = new CompareContext {Title = "EmptyCollectionSerialization"}; + // Initialize an OpenIdConnectConfiguration object with all collections empty. + var oidcWithEmptyCollections = new OpenIdConnectConfiguration(); + OpenIdConnectConfiguration.Write(oidcWithEmptyCollections, stream); + var emptyCollectionBytes = Encoding.UTF8.GetBytes("{}"); + + IdentityComparer.AreEqual(stream.ToArray(), emptyCollectionBytes, context); + + TestUtilities.AssertFailIfErrors(context); + } + [Fact] public void NonemptyCollectionSerialization() { @@ -345,5 +390,23 @@ public void NonemptyCollectionSerialization() } TestUtilities.AssertFailIfErrors(context); } + + [Fact] + public void NonemptyCollectionSerializationWithStream() + { + using MemoryStream stream = new(); + + var context = new CompareContext { Title = "NonemptyCollectionSerialization" }; + // Initialize an OpenIdConnectConfiguration object that has at least one element in each Collection. + var oidcWithAllCollections = OpenIdConnectConfiguration.Create(OpenIdConfigData.JsonAllValues); + var oidcWithAllCollectionsJson = OpenIdConnectConfiguration.Write(oidcWithAllCollections); + var oidcWithAllCollectionsBytes = Encoding.UTF8.GetBytes(oidcWithAllCollectionsJson); + + OpenIdConnectConfiguration.Write(oidcWithAllCollections, stream); + + IdentityComparer.AreBytesEqual(oidcWithAllCollectionsBytes, stream.GetBuffer(), context); + + TestUtilities.AssertFailIfErrors(context); + } } }