From 629e91f4cc27e606641ae740509a132fab71327f Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Mon, 10 Jun 2024 18:50:58 +0100 Subject: [PATCH 01/12] Serialize JWT --- .../Configuration/OpenIdConnectConfiguration.cs | 7 ++++++- .../Json/OpenIdConnectConfigurationSerializer.cs | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs index 0d3555ad69..873643f1a1 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs @@ -812,6 +812,11 @@ public bool ShouldSerializeUserInfoEndpointSigningAlgValuesSupported() return UserInfoEndpointSigningAlgValuesSupported.Count > 0; } -#endregion shouldserialize + /// + /// Gets or sets a value indicating whether the JsonWebKeys should be serialized. + /// + public bool ShouldSerializeJsonWebKeys { get; set; } + + #endregion shouldserialize } } diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs index f90a324d82..293049b936 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs @@ -12,6 +12,8 @@ using Utf8Bytes = Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdProviderMetadataUtf8Bytes; using JsonPrimitives = Microsoft.IdentityModel.Tokens.Json.JsonSerializerPrimitives; using MetadataName = Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdProviderMetadataNames; +using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Tokens.Json; namespace Microsoft.IdentityModel.Protocols.OpenIdConnect { @@ -279,6 +281,10 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (reader.ValueTextEquals(Utf8Bytes.UserInfoSigningAlgValuesSupported)) JsonPrimitives.ReadStrings(ref reader, config.UserInfoEndpointSigningAlgValuesSupported, MetadataName.UserInfoSigningAlgValuesSupported, ClassName, true); + + else if (reader.ValueTextEquals(JsonWebKeySetParameterNames.Keys)) + JsonWebKeySetSerializer.ReadKeys(ref reader, config.JsonWebKeySet); + #endregion else { @@ -578,6 +584,9 @@ public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration c if (config.ResponseTypesSupported.Count > 0) JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ResponseTypesSupported, config.ResponseTypesSupported); + if (config.ShouldSerializeJsonWebKeys && config.JsonWebKeySet != null && config.JsonWebKeySet.Keys.Count > 0) + JsonWebKeySetSerializer.Write(ref writer, config.JsonWebKeySet); + if (config.ScopesSupported.Count > 0) JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ScopesSupported, config.ScopesSupported); From 1a71e87ff39371571744d2912788c276ef4095de Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Tue, 11 Jun 2024 19:37:50 +0100 Subject: [PATCH 02/12] Add test and remove property from json serialization --- .../Configuration/OpenIdConnectConfiguration.cs | 1 + .../OpenIdConnectConfigurationTests.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs index 873643f1a1..b24639bd35 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs @@ -815,6 +815,7 @@ public bool ShouldSerializeUserInfoEndpointSigningAlgValuesSupported() /// /// Gets or sets a value indicating whether the JsonWebKeys should be serialized. /// + [JsonIgnore] public bool ShouldSerializeJsonWebKeys { get; set; } #endregion shouldserialize diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs index fc6690b7ce..4f04604fae 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs @@ -104,6 +104,7 @@ public void Defaults() Assert.NotNull(configuration.UserInfoEndpointEncryptionAlgValuesSupported); Assert.NotNull(configuration.UserInfoEndpointEncryptionEncValuesSupported); Assert.NotNull(configuration.UserInfoEndpointSigningAlgValuesSupported); + Assert.False(configuration.ShouldSerializeSigningKeys); } // If the OpenIdConnect metadata has a "SigningKeys" claim, it should NOT be deserialized into the corresponding OpenIdConnectConfiguration.SigningKeys property. From f2296aa7fa41ec5cc356e423c8a9df9a42fb465c Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Tue, 11 Jun 2024 21:01:45 +0100 Subject: [PATCH 03/12] Add test --- .../OpenIdConnectConfigurationTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs index 4f04604fae..e916d6c613 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs @@ -104,7 +104,7 @@ public void Defaults() Assert.NotNull(configuration.UserInfoEndpointEncryptionAlgValuesSupported); Assert.NotNull(configuration.UserInfoEndpointEncryptionEncValuesSupported); Assert.NotNull(configuration.UserInfoEndpointSigningAlgValuesSupported); - Assert.False(configuration.ShouldSerializeSigningKeys); + Assert.False(configuration.ShouldSerializeJsonWebKeys); } // If the OpenIdConnect metadata has a "SigningKeys" claim, it should NOT be deserialized into the corresponding OpenIdConnectConfiguration.SigningKeys property. From 9c97398e2b2c9d4b8df75bf601e2ca41aad667a2 Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Wed, 12 Jun 2024 21:23:44 +0100 Subject: [PATCH 04/12] Add mock configuration --- .../OpenIdConfigData.cs | 11 +++++++++++ .../OpenIdConnectSerializationTests.cs | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs index f887eccadd..242adfb623 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs @@ -594,6 +594,17 @@ public static OpenIdConnectConfiguration Default get => SetDefaultConfiguration(new OpenIdConnectConfiguration()); } + public static OpenIdConnectConfiguration WithJsonWebKeySet + { + get + { + var config = Default; + config.JsonWebKeySet = JsonUtilities.FullyPopulatedJsonWebKeySet(); + config.ShouldSerializeJsonWebKeys = true; + return config; + } + } + private static OpenIdConnectConfiguration SetDefaultConfiguration(OpenIdConnectConfiguration config) { AddToCollection(config.AcrValuesSupported, "acr_value1", "acr_value2", "acr_value3"); diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs index 9d28137c02..3787368589 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs @@ -139,6 +139,12 @@ public static TheoryData DesrializeTheoryData Json = JsonData.NullObject }); + theoryData.Add(new OpenIdConnectTheoryData("SerializeJsonWebKeySet") + { + CompareTo = OpenIdConfigData.WithJsonWebKeySet, + Json = "" + }); + return theoryData; } } From 6aacac0fc1e31ca8678d2a2f449b9545e2c0318e Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Fri, 14 Jun 2024 20:04:45 +0100 Subject: [PATCH 05/12] Add two test cases for (de)serialization --- .../OpenIdConnectConfigurationSerializer.cs | 74 ++++++++++--------- .../OpenIdConfigData.cs | 11 --- .../OpenIdConnectConfigurationTests.cs | 16 ++++ .../OpenIdConnectSerializationTests.cs | 9 ++- 4 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs index 293049b936..c250858c87 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs @@ -158,6 +158,14 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (reader.ValueTextEquals(Utf8Bytes.EndSessionEndpoint)) config.EndSessionEndpoint = JsonPrimitives.ReadString(ref reader, MetadataName.EndSessionEndpoint, ClassName, true); + else if (reader.ValueTextEquals(Encoding.UTF8.GetBytes(JsonWebKeySetParameterNames.Keys))) + { + reader.Read(); + if (config.JsonWebKeySet == null) + config.JsonWebKeySet = new JsonWebKeySet(); + JsonWebKeySetSerializer.Read(ref reader, config.JsonWebKeySet); + } + // FrontchannelLogoutSessionSupported and FrontchannelLogoutSupported are per spec 'boolean'. // We shipped pervious versions accepting a string and transforming to a boolean. else if (reader.ValueTextEquals(Utf8Bytes.FrontchannelLogoutSessionSupported)) @@ -282,9 +290,6 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (reader.ValueTextEquals(Utf8Bytes.UserInfoSigningAlgValuesSupported)) JsonPrimitives.ReadStrings(ref reader, config.UserInfoEndpointSigningAlgValuesSupported, MetadataName.UserInfoSigningAlgValuesSupported, ClassName, true); - else if (reader.ValueTextEquals(JsonWebKeySetParameterNames.Keys)) - JsonWebKeySetSerializer.ReadKeys(ref reader, config.JsonWebKeySet); - #endregion else { @@ -359,91 +364,91 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (propertyName.Equals(MetadataName.IdTokenEncryptionEncValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.IdTokenEncryptionEncValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName.IdTokenSigningAlgValuesSupported , StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.IdTokenSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.IdTokenSigningAlgValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. IntrospectionEndpoint, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.IntrospectionEndpoint, StringComparison.OrdinalIgnoreCase)) config.IntrospectionEndpoint = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. IntrospectionEndpointAuthMethodsSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.IntrospectionEndpointAuthMethodsSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.IntrospectionEndpointAuthMethodsSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. IntrospectionEndpointAuthSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.IntrospectionEndpointAuthSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.IntrospectionEndpointAuthSigningAlgValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. Issuer, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.Issuer, StringComparison.OrdinalIgnoreCase)) config.Issuer = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. JwksUri, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.JwksUri, StringComparison.OrdinalIgnoreCase)) config.JwksUri = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. LogoutSessionSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.LogoutSessionSupported, StringComparison.OrdinalIgnoreCase)) config.LogoutSessionSupported = JsonPrimitives.ReadBoolean(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. OpPolicyUri, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.OpPolicyUri, StringComparison.OrdinalIgnoreCase)) config.OpPolicyUri = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. OpTosUri, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.OpTosUri, StringComparison.OrdinalIgnoreCase)) config.OpTosUri = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. RegistrationEndpoint, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.RegistrationEndpoint, StringComparison.OrdinalIgnoreCase)) config.RegistrationEndpoint = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. RequestObjectEncryptionAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.RequestObjectEncryptionAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.RequestObjectEncryptionAlgValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. RequestObjectEncryptionEncValuesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.RequestObjectEncryptionEncValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.RequestObjectEncryptionEncValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. RequestObjectSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.RequestObjectSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.RequestObjectSigningAlgValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. RequestParameterSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.RequestParameterSupported, StringComparison.OrdinalIgnoreCase)) config.RequestParameterSupported = JsonPrimitives.ReadBoolean(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. RequestUriParameterSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.RequestUriParameterSupported, StringComparison.OrdinalIgnoreCase)) config.RequestUriParameterSupported = JsonPrimitives.ReadBoolean(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. RequireRequestUriRegistration, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.RequireRequestUriRegistration, StringComparison.OrdinalIgnoreCase)) config.RequireRequestUriRegistration = JsonPrimitives.ReadBoolean(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. ResponseModesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.ResponseModesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.ResponseModesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. ResponseTypesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.ResponseTypesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.ResponseTypesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. ScopesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.ScopesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.ScopesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. ServiceDocumentation, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.ServiceDocumentation, StringComparison.OrdinalIgnoreCase)) config.ServiceDocumentation = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. SubjectTypesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.SubjectTypesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.SubjectTypesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. TokenEndpoint, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.TokenEndpoint, StringComparison.OrdinalIgnoreCase)) config.TokenEndpoint = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. TokenEndpointAuthMethodsSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.TokenEndpointAuthMethodsSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.TokenEndpointAuthMethodsSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. TokenEndpointAuthSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.TokenEndpointAuthSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.TokenEndpointAuthSigningAlgValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. UILocalesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.UILocalesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.UILocalesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. UserInfoEncryptionAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.UserInfoEncryptionAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.UserInfoEndpointEncryptionAlgValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. UserInfoEncryptionEncValuesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.UserInfoEncryptionEncValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.UserInfoEndpointEncryptionEncValuesSupported, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. UserInfoEndpoint, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.UserInfoEndpoint, StringComparison.OrdinalIgnoreCase)) config.UserInfoEndpoint = JsonPrimitives.ReadString(ref reader, propertyName, ClassName); - else if (propertyName.Equals(MetadataName. UserInfoSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) + else if (propertyName.Equals(MetadataName.UserInfoSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.UserInfoEndpointSigningAlgValuesSupported, propertyName, ClassName); } @@ -585,7 +590,10 @@ public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration c JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ResponseTypesSupported, config.ResponseTypesSupported); if (config.ShouldSerializeJsonWebKeys && config.JsonWebKeySet != null && config.JsonWebKeySet.Keys.Count > 0) + { + writer.WritePropertyName(Encoding.UTF8.GetBytes(JsonWebKeySetParameterNames.Keys)); JsonWebKeySetSerializer.Write(ref writer, config.JsonWebKeySet); + } if (config.ScopesSupported.Count > 0) JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ScopesSupported, config.ScopesSupported); @@ -619,7 +627,7 @@ public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration c if (config.UserInfoEndpointSigningAlgValuesSupported.Count > 0) JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.UserInfoSigningAlgValuesSupported, config.UserInfoEndpointSigningAlgValuesSupported); - + if (config.AdditionalData.Count > 0) JsonPrimitives.WriteObjects(ref writer, config.AdditionalData); diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs index 242adfb623..f887eccadd 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs @@ -594,17 +594,6 @@ public static OpenIdConnectConfiguration Default get => SetDefaultConfiguration(new OpenIdConnectConfiguration()); } - public static OpenIdConnectConfiguration WithJsonWebKeySet - { - get - { - var config = Default; - config.JsonWebKeySet = JsonUtilities.FullyPopulatedJsonWebKeySet(); - config.ShouldSerializeJsonWebKeys = true; - return config; - } - } - private static OpenIdConnectConfiguration SetDefaultConfiguration(OpenIdConnectConfiguration config) { AddToCollection(config.AcrValuesSupported, "acr_value1", "acr_value2", "acr_value3"); diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs index e916d6c613..9917fb517f 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs @@ -126,6 +126,22 @@ public void DeserializeOpenIdConnectConfigurationWithSigningKeys() TestUtilities.AssertFailIfErrors(context); } + [Fact] + public void DeserializeOpenIdConnectConfigurationWithJsonWebKeySet() + { + TestUtilities.WriteHeader($"{this}.DeserializeOpenIdConnectConfigurationWithJsonWebKeySet"); + var context = new CompareContext(); + var config = OpenIdConfigData.FullyPopulatedWithKeys; + config.ShouldSerializeJsonWebKeys = true; + var json = OpenIdConnectConfiguration.Write(config); + var actualConfig = OpenIdConnectConfiguration.Create(json); + + // "JsonWebKeySet" should be identical + IdentityComparer.AreEqual(OpenIdConfigData.FullyPopulatedWithKeys.JsonWebKeySet, actualConfig.JsonWebKeySet, context); + + TestUtilities.AssertFailIfErrors(context); + } + [Fact] public void GetSets() { diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs index 3787368589..d67305e561 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs @@ -40,7 +40,7 @@ public static TheoryData DesrializeTheoryData get { TheoryData theoryData = new TheoryData(); - + // the reason to replace AdditionalData with upper case is because the test deserializes uppercase and lowercase. // we wanted to leave the data sets in original form from discovery to be used in other tests. theoryData.Add(new OpenIdConnectTheoryData("AADCommonV1") @@ -138,15 +138,16 @@ public static TheoryData DesrializeTheoryData CompareTo = OpenIdConfigData.NullConfig, Json = JsonData.NullObject }); - + theoryData.Add(new OpenIdConnectTheoryData("SerializeJsonWebKeySet") { - CompareTo = OpenIdConfigData.WithJsonWebKeySet, - Json = "" + CompareTo = OpenIdConfigData.FullyPopulatedWithKeys, + Json = OpenIdConfigData.JsonAllValues }); return theoryData; } } + } } From 0db3e87d636ea3da3a773866af9baca1af4f0aa0 Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Tue, 18 Jun 2024 16:49:04 +0100 Subject: [PATCH 06/12] Fix test --- .../OpenIdConnectConfigurationSerializer.cs | 10 + .../OpenIdConfigData.cs | 207 ++++++++++++++++++ .../OpenIdConnectSerializationTests.cs | 7 +- 3 files changed, 220 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs index 9a151669bc..c92a54cf14 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs @@ -68,6 +68,7 @@ public static readonly "INTROSPECTION_ENDPOINT_AUTH_METHODS_SUPPORTED", "INTROSPECTION_ENDPOINT_AUTH_SIGNING_ALG_VALUES_SUPPORTED", "JWKS_URI", + "KEYS", "ISSUER", "LOGOUT_SESSION_SUPPORTED", "OP_POLICY_URI", @@ -215,6 +216,7 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC if (config.JsonWebKeySet == null) config.JsonWebKeySet = new JsonWebKeySet(); JsonWebKeySetSerializer.Read(ref reader, config.JsonWebKeySet); + config.ShouldSerializeJsonWebKeys = true; } // FrontchannelLogoutSessionSupported and FrontchannelLogoutSupported are per spec 'boolean'. @@ -557,6 +559,14 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (propertyName.Equals(MetadataName.UserInfoSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase)) JsonPrimitives.ReadStrings(ref reader, config.UserInfoEndpointSigningAlgValuesSupported, propertyName, ClassName); + + else if (propertyName.Equals(JsonWebKeySetParameterNames.Keys, StringComparison.OrdinalIgnoreCase)) + { + if (config.JsonWebKeySet == null) + config.JsonWebKeySet = new JsonWebKeySet(); + JsonWebKeySetSerializer.Read(ref reader, config.JsonWebKeySet); + config.ShouldSerializeJsonWebKeys = true; + } } #endregion case-insensitive } diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs index 1f60d43365..f8169eba2b 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs @@ -17,6 +17,17 @@ public class OpenIdConfigData { public static OpenIdConnectConfiguration FullyPopulated = new OpenIdConnectConfiguration(); + public static OpenIdConnectConfiguration DefaultConfigWithJWK + { + get + { + var config = Default; + config.JsonWebKeySet = DataSets.JsonWebKeySet1; + config.ShouldSerializeJsonWebKeys = true; + return config; + } + } + public static OpenIdConnectConfiguration FullyPopulatedWithKeys { get @@ -65,6 +76,202 @@ public static OpenIdConnectConfiguration FullyPopulatedWithKeys public static string OpenIdConnectMetadataFileEnd2End = @"OpenIdConnectMetadataEnd2End.json"; public static string OpenIdConnectMetadataFileEnd2EndEC = @"OpenIdConnectMetadataEnd2EndEC.json"; public static string JsonWebKeySetBadUriFile = @"OpenIdConnectMetadataJsonWebKeySetBadUri.json"; + public static string JsonWithJWK = @"{ + ""acr_values_supported"": [ + ""acr_value1"", + ""acr_value2"", + ""acr_value3"" + ], + ""authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/authorize"", + ""backchannel_authentication_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/bc-authorize"", + ""backchannel_authentication_request_signing_alg_values_supported"": [ + ""ES384"", + ""ES512"" + ], + ""backchannel_token_delivery_modes_supported"": [ + ""poll"", + ""ping"" + ], + ""check_session_iframe"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/checksession"", + ""claims_supported"": [ + ""sub"", + ""iss"", + ""aud"", + ""exp"", + ""iat"", + ""auth_time"", + ""acr"", + ""amr"", + ""nonce"", + ""email"", + ""given_name"", + ""family_name"", + ""nickname"" + ], + ""claims_locales_supported"": [ + ""claim_local1"", + ""claim_local2"", + ""claim_local3"" + ], + ""claims_parameter_supported"": true, + ""claim_types_supported"": [ + ""Normal Claims"", + ""Aggregated Claims"", + ""Distributed Claims"" + ], + ""code_challenge_methods_supported"": [ + ""plain"", + ""S256"" + ], + ""device_authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/devicecode"", + ""display_values_supported"": [ + ""displayValue1"", + ""displayValue2"", + ""displayValue3"" + ], + ""dpop_signing_alg_values_supported"": [ + ""ES384"", + ""ES512"" + ], + ""end_session_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/logout"", + ""frontchannel_logout_session_supported"": ""true"", + ""frontchannel_logout_supported"": ""true"", + ""grant_types_supported"": [ + ""authorization_code"", + ""implicit"" + ], + ""http_logout_supported"": true, + ""id_token_encryption_alg_values_supported"": [ + ""RSA1_5"", + ""A256KW"" + ], + ""id_token_encryption_enc_values_supported"": [ + ""A128CBC-HS256"", + ""A256CBC-HS512"" + ], + ""id_token_signing_alg_values_supported"": [ + ""RS256"" + ], + ""introspection_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/introspect"", + ""introspection_endpoint_auth_methods_supported"": [ + ""client_secret_post"", + ""private_key_jwt"" + ], + ""introspection_endpoint_auth_signing_alg_values_supported"": [ + ""ES192"", + ""ES256"" + ], + ""issuer"": ""https://sts.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/"", + ""jwks_uri"": ""JsonWebKeySet.json"", + ""logout_session_supported"": true, + ""op_policy_uri"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/op_policy_uri"", + ""op_tos_uri"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/op_tos_uri"", + ""prompt_values_supported"": [ + ""none"", + ""login"", + ""consent"" + ], + ""pushed_authorization_request_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/par"", + ""request_object_encryption_alg_values_supported"": [ + ""A192KW"", + ""A256KW"" + ], + ""request_object_encryption_enc_values_supported"": [ + ""A192GCM"", + ""A256GCM"" + ], + ""request_object_signing_alg_values_supported"": [ + ""PS256"", + ""PS512"" + ], + ""request_parameter_supported"": true, + ""request_uri_parameter_supported"": true, + ""require_request_uri_registration"": true, + ""response_modes_supported"": [ + ""query"", + ""fragment"", + ""form_post"" + ], + ""response_types_supported"": [ + ""code"", + ""id_token"", + ""code id_token"" + ], + ""keys"": { + ""keys"": [ + { + ""alg"": ""SHA256"", + ""e"": ""AQAB"", + ""key_ops"": [ + ""signing"" + ], + ""kid"": ""NGTFvdK-fythEuLwjpwAJOM9n-A"", + ""kty"": ""RSA"", + ""n"": ""rCz8Sn3GGXmikH2MdTeGY1D711EORX/lVXpr+ecGgqfUWF8MPB07XkYuJ54DAuYT318+2XrzMjOtqkT94VkXmxv6dFGhG8YZ8vNMPd4tdj9c0lpvWQdqXtL1TlFRpD/P6UMEigfN0c9oWDg9U7Ilymgei0UXtf1gtcQbc5sSQU0S4vr9YJp2gLFIGK11Iqg4XSGdcI0QWLLkkC6cBukhVnd6BCYbLjTYy3fNs4DzNdemJlxGl8sLexFytBF6YApvSdus3nFXaMCtBGx16HzkK9ne3lobAwL2o79bP4imEGqg+ibvyNmbrwFGnQrBc1jTF9LyQX9q+louxVfHs6ZiVw=="", + ""use"": ""sig"", + ""x5c"": [ + ""MIIDPjCCAiqgAwIBAgIQVWmXY/+9RqFA/OG9kFulHDAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTIwNjA3MDcwMDAwWhcNMTQwNjA3MDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArCz8Sn3GGXmikH2MdTeGY1D711EORX/lVXpr+ecGgqfUWF8MPB07XkYuJ54DAuYT318+2XrzMjOtqkT94VkXmxv6dFGhG8YZ8vNMPd4tdj9c0lpvWQdqXtL1TlFRpD/P6UMEigfN0c9oWDg9U7Ilymgei0UXtf1gtcQbc5sSQU0S4vr9YJp2gLFIGK11Iqg4XSGdcI0QWLLkkC6cBukhVnd6BCYbLjTYy3fNs4DzNdemJlxGl8sLexFytBF6YApvSdus3nFXaMCtBGx16HzkK9ne3lobAwL2o79bP4imEGqg+ibvyNmbrwFGnQrBc1jTF9LyQX9q+louxVfHs6ZiVwIDAQABo2IwYDBeBgNVHQEEVzBVgBCxDDsLd8xkfOLKm4Q/SzjtoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQVWmXY/+9RqFA/OG9kFulHDAJBgUrDgMCHQUAA4IBAQAkJtxxm/ErgySlNk69+1odTMP8Oy6L0H17z7XGG3w4TqvTUSWaxD4hSFJ0e7mHLQLQD7oV/erACXwSZn2pMoZ89MBDjOMQA+e6QzGB7jmSzPTNmQgMLA8fWCfqPrz6zgH+1F1gNp8hJY57kfeVPBiyjuBmlTEBsBlzolY9dd/55qqfQk6cgSeCbHCy/RU/iep0+UsRMlSgPNNmqhj5gmN2AFVCN96zF694LwuPae5CeR2ZcVknexOWHYjFM0MgUSw0ubnGl0h9AJgGyhvNGcjQqu9vd1xkupFgaN+f7P3p3EVN5csBg5H94jEcQZT7EKeTiZ6bTrpDAnrr8tDCy8ng"" + ], + ""x5t"": ""NGTFvdK-fythEuLwjpwAJOM9n-A"", + ""x5u"": ""https://jsonkeyurl"" + }, + { + ""alg"": ""SHA256"", + ""e"": ""AQAB"", + ""kid"": ""kriMPdmBvx68skT8-mPAB3BseeA"", + ""kty"": ""RSA"", + ""n"": ""kSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuw=="", + ""use"": ""sig"", + ""x5c"": [ + ""MIIDPjCCAiqgAwIBAgIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTQwMTAxMDcwMDAwWhcNMTYwMTAxMDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuwIDAQABo2IwYDBeBgNVHQEEVzBVgBDLebM6bK3BjWGqIBrBNFeNoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAA4IBAQCJ4JApryF77EKC4zF5bUaBLQHQ1PNtA1uMDbdNVGKCmSf8M65b8h0NwlIjGGGy/unK8P6jWFdm5IlZ0YPTOgzcRZguXDPj7ajyvlVEQ2K2ICvTYiRQqrOhEhZMSSZsTKXFVwNfW6ADDkN3bvVOVbtpty+nBY5UqnI7xbcoHLZ4wYD251uj5+lo13YLnsVrmQ16NCBYq2nQFNPuNJw6t3XUbwBHXpF46aLT1/eGf/7Xx6iy8yPJX4DyrpFTutDz882RWofGEO5t4Cw+zZg70dJ/hH/ODYRMorfXEW+8uKmXMKmX2wyxMKvfiPbTy5LmAU8Jvjs2tLg4rOBcXWLAIarZ"" + ], + ""x5t"": ""kriMPdmBvx68skT8-mPAB3BseeA"" + } + ] + }, + ""scopes_supported"": [ + ""openid"" + ], + ""revocation_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/revocation"", + ""revocation_endpoint_auth_methods_supported"": [ + ""client_secret_post"", + ""client_secret_basic"" + ], + ""revocation_endpoint_auth_signing_alg_values_supported"": [ + ""ES192"", + ""ES256"" + ], + ""service_documentation"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/service_documentation"", + ""subject_types_supported"": [ + ""pairwise"" + ], + ""token_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/token"", + ""token_endpoint_auth_methods_supported"": [ + ""client_secret_post"", + ""private_key_jwt"" + ], + ""token_endpoint_auth_signing_alg_values_supported"": [ + ""ES192"", + ""ES256"" + ], + ""ui_locales_supported"": [ + ""hak-CN"", + ""en-us"" + ], + ""userinfo_endpoint"": ""https://login.microsoftonline.com/add29489-7269-41f4-8841-b63c95564420/openid/userinfo"", + ""userinfo_encryption_alg_values_supported"": [ + ""ECDH-ES+A128KW"", + ""ECDH-ES+A192KW"" + ], + ""userinfo_encryption_enc_values_supported"": [ + ""A256CBC-HS512"", + ""A128CBC-HS256"" + ], + ""userinfo_signing_alg_values_supported"": [ + ""ES384"", + ""ES512"" + ] + }"; public static string JsonAllValues = @"{ ""acr_values_supported"": [""acr_value1"", ""acr_value2"", ""acr_value3""], ""authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/authorize"", diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs index fad09149d2..2be8b56fb0 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs @@ -40,7 +40,6 @@ public static TheoryData DesrializeTheoryData get { TheoryData theoryData = new TheoryData(); - // the reason to replace AdditionalData with upper case is because the test deserializes uppercase and lowercase. // we wanted to leave the data sets in original form from discovery to be used in other tests. theoryData.Add(new OpenIdConnectTheoryData("AADCommonV1") @@ -138,11 +137,11 @@ public static TheoryData DesrializeTheoryData CompareTo = OpenIdConfigData.NullConfig, Json = JsonData.NullObject }); - + theoryData.Add(new OpenIdConnectTheoryData("SerializeJsonWebKeySet") { - CompareTo = OpenIdConfigData.FullyPopulatedWithKeys, - Json = OpenIdConfigData.JsonAllValues + CompareTo = OpenIdConfigData.DefaultConfigWithJWK, + Json = OpenIdConfigData.JsonWithJWK }); return theoryData; From 19133a0db34d97794631d625c71413f076598ad2 Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Tue, 18 Jun 2024 17:25:28 +0100 Subject: [PATCH 07/12] Increase number of props --- .../OpenIdConnectConfigurationTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs index 6d57ad2a65..f4b7ce2b29 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs @@ -158,8 +158,8 @@ public void GetSets() OpenIdConnectConfiguration configuration = new OpenIdConnectConfiguration(); Type type = typeof(OpenIdConnectConfiguration); PropertyInfo[] properties = type.GetProperties(); - if (properties.Length != 63) - Assert.True(false, "Number of properties has changed from 63 to: " + properties.Length + ", adjust tests"); + if (properties.Length != 64) + Assert.True(false, "Number of properties has changed from 64 to: " + properties.Length + ", adjust tests"); TestUtilities.CallAllPublicInstanceAndStaticPropertyGets(configuration, "OpenIdConnectConfiguration_GetSets"); From c7483c7ceff6a9da52ab364bb35e2cd090d1af9e Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Wed, 19 Jun 2024 17:53:23 +0100 Subject: [PATCH 08/12] Fix error --- .../OpenIdConnectConfigurationSerializer.cs | 17 +- .../Json/JsonWebKeySetSerializer.cs | 9 +- .../OpenIdConfigData.cs | 382 +++++++++--------- .../OpenIdConnectSerializationTests.cs | 13 +- 4 files changed, 211 insertions(+), 210 deletions(-) diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs index c92a54cf14..01758c26af 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs @@ -212,11 +212,12 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (reader.ValueTextEquals(Encoding.UTF8.GetBytes(JsonWebKeySetParameterNames.Keys))) { - reader.Read(); + config.ShouldSerializeJsonWebKeys = true; if (config.JsonWebKeySet == null) config.JsonWebKeySet = new JsonWebKeySet(); - JsonWebKeySetSerializer.Read(ref reader, config.JsonWebKeySet); - config.ShouldSerializeJsonWebKeys = true; + // Skip key "Keys" + reader.Read(); + JsonWebKeySetSerializer.ReadKeys(ref reader, config.JsonWebKeySet); } // FrontchannelLogoutSessionSupported and FrontchannelLogoutSupported are per spec 'boolean'. @@ -562,10 +563,11 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (propertyName.Equals(JsonWebKeySetParameterNames.Keys, StringComparison.OrdinalIgnoreCase)) { + config.ShouldSerializeJsonWebKeys = true; if (config.JsonWebKeySet == null) config.JsonWebKeySet = new JsonWebKeySet(); - JsonWebKeySetSerializer.Read(ref reader, config.JsonWebKeySet); - config.ShouldSerializeJsonWebKeys = true; + // Skip key "Keys" + JsonWebKeySetSerializer.ReadKeys(ref reader, config.JsonWebKeySet); } } #endregion case-insensitive @@ -739,10 +741,7 @@ public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration c JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ResponseTypesSupported, config.ResponseTypesSupported); if (config.ShouldSerializeJsonWebKeys && config.JsonWebKeySet != null && config.JsonWebKeySet.Keys.Count > 0) - { - writer.WritePropertyName(Encoding.UTF8.GetBytes(JsonWebKeySetParameterNames.Keys)); - JsonWebKeySetSerializer.Write(ref writer, config.JsonWebKeySet); - } + JsonWebKeySetSerializer.Write(ref writer, config.JsonWebKeySet, shouldWriteObject: false); if (config.ScopesSupported.Count > 0) JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ScopesSupported, config.ScopesSupported); diff --git a/src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySetSerializer.cs b/src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySetSerializer.cs index cca32dd494..5b1ef6f6bd 100644 --- a/src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySetSerializer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySetSerializer.cs @@ -136,9 +136,11 @@ public static string Write(JsonWebKeySet jsonWebKeySet) /// /// /// - public static void Write(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet) + /// + public static void Write(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet, bool shouldWriteObject = true) { - writer.WriteStartObject(); + if (shouldWriteObject) + writer.WriteStartObject(); writer.WritePropertyName(JsonWebKeyParameterUtf8Bytes.Keys); writer.WriteStartArray(); @@ -151,7 +153,8 @@ public static void Write(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet) if (jsonWebKeySet.AdditionalData.Count > 0) JsonSerializerPrimitives.WriteObjects(ref writer, jsonWebKeySet.AdditionalData); - writer.WriteEndObject(); + if (shouldWriteObject) + writer.WriteEndObject(); } #endregion diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs index f8169eba2b..cd56c49e9a 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs @@ -77,201 +77,199 @@ public static OpenIdConnectConfiguration FullyPopulatedWithKeys public static string OpenIdConnectMetadataFileEnd2EndEC = @"OpenIdConnectMetadataEnd2EndEC.json"; public static string JsonWebKeySetBadUriFile = @"OpenIdConnectMetadataJsonWebKeySetBadUri.json"; public static string JsonWithJWK = @"{ - ""acr_values_supported"": [ - ""acr_value1"", - ""acr_value2"", - ""acr_value3"" - ], - ""authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/authorize"", - ""backchannel_authentication_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/bc-authorize"", - ""backchannel_authentication_request_signing_alg_values_supported"": [ - ""ES384"", - ""ES512"" - ], - ""backchannel_token_delivery_modes_supported"": [ - ""poll"", - ""ping"" - ], - ""check_session_iframe"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/checksession"", - ""claims_supported"": [ - ""sub"", - ""iss"", - ""aud"", - ""exp"", - ""iat"", - ""auth_time"", - ""acr"", - ""amr"", - ""nonce"", - ""email"", - ""given_name"", - ""family_name"", - ""nickname"" - ], - ""claims_locales_supported"": [ - ""claim_local1"", - ""claim_local2"", - ""claim_local3"" - ], - ""claims_parameter_supported"": true, - ""claim_types_supported"": [ - ""Normal Claims"", - ""Aggregated Claims"", - ""Distributed Claims"" - ], - ""code_challenge_methods_supported"": [ - ""plain"", - ""S256"" - ], - ""device_authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/devicecode"", - ""display_values_supported"": [ - ""displayValue1"", - ""displayValue2"", - ""displayValue3"" - ], - ""dpop_signing_alg_values_supported"": [ - ""ES384"", - ""ES512"" - ], - ""end_session_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/logout"", - ""frontchannel_logout_session_supported"": ""true"", - ""frontchannel_logout_supported"": ""true"", - ""grant_types_supported"": [ - ""authorization_code"", - ""implicit"" - ], - ""http_logout_supported"": true, - ""id_token_encryption_alg_values_supported"": [ - ""RSA1_5"", - ""A256KW"" - ], - ""id_token_encryption_enc_values_supported"": [ - ""A128CBC-HS256"", - ""A256CBC-HS512"" - ], - ""id_token_signing_alg_values_supported"": [ - ""RS256"" - ], - ""introspection_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/introspect"", - ""introspection_endpoint_auth_methods_supported"": [ - ""client_secret_post"", - ""private_key_jwt"" - ], - ""introspection_endpoint_auth_signing_alg_values_supported"": [ - ""ES192"", - ""ES256"" - ], - ""issuer"": ""https://sts.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/"", - ""jwks_uri"": ""JsonWebKeySet.json"", - ""logout_session_supported"": true, - ""op_policy_uri"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/op_policy_uri"", - ""op_tos_uri"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/op_tos_uri"", - ""prompt_values_supported"": [ - ""none"", - ""login"", - ""consent"" - ], - ""pushed_authorization_request_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/par"", - ""request_object_encryption_alg_values_supported"": [ - ""A192KW"", - ""A256KW"" - ], - ""request_object_encryption_enc_values_supported"": [ - ""A192GCM"", - ""A256GCM"" - ], - ""request_object_signing_alg_values_supported"": [ - ""PS256"", - ""PS512"" - ], - ""request_parameter_supported"": true, - ""request_uri_parameter_supported"": true, - ""require_request_uri_registration"": true, - ""response_modes_supported"": [ - ""query"", - ""fragment"", - ""form_post"" - ], - ""response_types_supported"": [ - ""code"", - ""id_token"", - ""code id_token"" - ], - ""keys"": { - ""keys"": [ - { - ""alg"": ""SHA256"", - ""e"": ""AQAB"", - ""key_ops"": [ - ""signing"" - ], - ""kid"": ""NGTFvdK-fythEuLwjpwAJOM9n-A"", - ""kty"": ""RSA"", - ""n"": ""rCz8Sn3GGXmikH2MdTeGY1D711EORX/lVXpr+ecGgqfUWF8MPB07XkYuJ54DAuYT318+2XrzMjOtqkT94VkXmxv6dFGhG8YZ8vNMPd4tdj9c0lpvWQdqXtL1TlFRpD/P6UMEigfN0c9oWDg9U7Ilymgei0UXtf1gtcQbc5sSQU0S4vr9YJp2gLFIGK11Iqg4XSGdcI0QWLLkkC6cBukhVnd6BCYbLjTYy3fNs4DzNdemJlxGl8sLexFytBF6YApvSdus3nFXaMCtBGx16HzkK9ne3lobAwL2o79bP4imEGqg+ibvyNmbrwFGnQrBc1jTF9LyQX9q+louxVfHs6ZiVw=="", - ""use"": ""sig"", - ""x5c"": [ - ""MIIDPjCCAiqgAwIBAgIQVWmXY/+9RqFA/OG9kFulHDAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTIwNjA3MDcwMDAwWhcNMTQwNjA3MDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArCz8Sn3GGXmikH2MdTeGY1D711EORX/lVXpr+ecGgqfUWF8MPB07XkYuJ54DAuYT318+2XrzMjOtqkT94VkXmxv6dFGhG8YZ8vNMPd4tdj9c0lpvWQdqXtL1TlFRpD/P6UMEigfN0c9oWDg9U7Ilymgei0UXtf1gtcQbc5sSQU0S4vr9YJp2gLFIGK11Iqg4XSGdcI0QWLLkkC6cBukhVnd6BCYbLjTYy3fNs4DzNdemJlxGl8sLexFytBF6YApvSdus3nFXaMCtBGx16HzkK9ne3lobAwL2o79bP4imEGqg+ibvyNmbrwFGnQrBc1jTF9LyQX9q+louxVfHs6ZiVwIDAQABo2IwYDBeBgNVHQEEVzBVgBCxDDsLd8xkfOLKm4Q/SzjtoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQVWmXY/+9RqFA/OG9kFulHDAJBgUrDgMCHQUAA4IBAQAkJtxxm/ErgySlNk69+1odTMP8Oy6L0H17z7XGG3w4TqvTUSWaxD4hSFJ0e7mHLQLQD7oV/erACXwSZn2pMoZ89MBDjOMQA+e6QzGB7jmSzPTNmQgMLA8fWCfqPrz6zgH+1F1gNp8hJY57kfeVPBiyjuBmlTEBsBlzolY9dd/55qqfQk6cgSeCbHCy/RU/iep0+UsRMlSgPNNmqhj5gmN2AFVCN96zF694LwuPae5CeR2ZcVknexOWHYjFM0MgUSw0ubnGl0h9AJgGyhvNGcjQqu9vd1xkupFgaN+f7P3p3EVN5csBg5H94jEcQZT7EKeTiZ6bTrpDAnrr8tDCy8ng"" - ], - ""x5t"": ""NGTFvdK-fythEuLwjpwAJOM9n-A"", - ""x5u"": ""https://jsonkeyurl"" - }, - { - ""alg"": ""SHA256"", - ""e"": ""AQAB"", - ""kid"": ""kriMPdmBvx68skT8-mPAB3BseeA"", - ""kty"": ""RSA"", - ""n"": ""kSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuw=="", - ""use"": ""sig"", - ""x5c"": [ - ""MIIDPjCCAiqgAwIBAgIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTQwMTAxMDcwMDAwWhcNMTYwMTAxMDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuwIDAQABo2IwYDBeBgNVHQEEVzBVgBDLebM6bK3BjWGqIBrBNFeNoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAA4IBAQCJ4JApryF77EKC4zF5bUaBLQHQ1PNtA1uMDbdNVGKCmSf8M65b8h0NwlIjGGGy/unK8P6jWFdm5IlZ0YPTOgzcRZguXDPj7ajyvlVEQ2K2ICvTYiRQqrOhEhZMSSZsTKXFVwNfW6ADDkN3bvVOVbtpty+nBY5UqnI7xbcoHLZ4wYD251uj5+lo13YLnsVrmQ16NCBYq2nQFNPuNJw6t3XUbwBHXpF46aLT1/eGf/7Xx6iy8yPJX4DyrpFTutDz882RWofGEO5t4Cw+zZg70dJ/hH/ODYRMorfXEW+8uKmXMKmX2wyxMKvfiPbTy5LmAU8Jvjs2tLg4rOBcXWLAIarZ"" - ], - ""x5t"": ""kriMPdmBvx68skT8-mPAB3BseeA"" - } - ] - }, - ""scopes_supported"": [ - ""openid"" - ], - ""revocation_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/revocation"", - ""revocation_endpoint_auth_methods_supported"": [ - ""client_secret_post"", - ""client_secret_basic"" - ], - ""revocation_endpoint_auth_signing_alg_values_supported"": [ - ""ES192"", - ""ES256"" - ], - ""service_documentation"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/service_documentation"", - ""subject_types_supported"": [ - ""pairwise"" - ], - ""token_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/token"", - ""token_endpoint_auth_methods_supported"": [ - ""client_secret_post"", - ""private_key_jwt"" - ], - ""token_endpoint_auth_signing_alg_values_supported"": [ - ""ES192"", - ""ES256"" - ], - ""ui_locales_supported"": [ - ""hak-CN"", - ""en-us"" + ""acr_values_supported"": [ + ""acr_value1"", + ""acr_value2"", + ""acr_value3"" + ], + ""authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/authorize"", + ""backchannel_authentication_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/bc-authorize"", + ""backchannel_authentication_request_signing_alg_values_supported"": [ + ""ES384"", + ""ES512"" + ], + ""backchannel_token_delivery_modes_supported"": [ + ""poll"", + ""ping"" + ], + ""check_session_iframe"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/checksession"", + ""claims_supported"": [ + ""sub"", + ""iss"", + ""aud"", + ""exp"", + ""iat"", + ""auth_time"", + ""acr"", + ""amr"", + ""nonce"", + ""email"", + ""given_name"", + ""family_name"", + ""nickname"" + ], + ""claims_locales_supported"": [ + ""claim_local1"", + ""claim_local2"", + ""claim_local3"" + ], + ""claims_parameter_supported"": true, + ""claim_types_supported"": [ + ""Normal Claims"", + ""Aggregated Claims"", + ""Distributed Claims"" + ], + ""code_challenge_methods_supported"": [ + ""plain"", + ""S256"" + ], + ""device_authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/devicecode"", + ""display_values_supported"": [ + ""displayValue1"", + ""displayValue2"", + ""displayValue3"" + ], + ""dpop_signing_alg_values_supported"": [ + ""ES384"", + ""ES512"" + ], + ""end_session_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/logout"", + ""frontchannel_logout_session_supported"": ""true"", + ""frontchannel_logout_supported"": ""true"", + ""grant_types_supported"": [ + ""authorization_code"", + ""implicit"" + ], + ""http_logout_supported"": true, + ""id_token_encryption_alg_values_supported"": [ + ""RSA1_5"", + ""A256KW"" + ], + ""id_token_encryption_enc_values_supported"": [ + ""A128CBC-HS256"", + ""A256CBC-HS512"" + ], + ""id_token_signing_alg_values_supported"": [ + ""RS256"" + ], + ""introspection_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/introspect"", + ""introspection_endpoint_auth_methods_supported"": [ + ""client_secret_post"", + ""private_key_jwt"" + ], + ""introspection_endpoint_auth_signing_alg_values_supported"": [ + ""ES192"", + ""ES256"" + ], + ""issuer"": ""https://sts.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/"", + ""jwks_uri"": ""JsonWebKeySet.json"", + ""logout_session_supported"": true, + ""op_policy_uri"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/op_policy_uri"", + ""op_tos_uri"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/op_tos_uri"", + ""prompt_values_supported"": [ + ""none"", + ""login"", + ""consent"" + ], + ""pushed_authorization_request_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/par"", + ""request_object_encryption_alg_values_supported"": [ + ""A192KW"", + ""A256KW"" + ], + ""request_object_encryption_enc_values_supported"": [ + ""A192GCM"", + ""A256GCM"" + ], + ""request_object_signing_alg_values_supported"": [ + ""PS256"", + ""PS512"" + ], + ""request_parameter_supported"": true, + ""request_uri_parameter_supported"": true, + ""require_request_uri_registration"": true, + ""response_modes_supported"": [ + ""query"", + ""fragment"", + ""form_post"" + ], + ""response_types_supported"": [ + ""code"", + ""id_token"", + ""code id_token"" + ], + ""keys"": [ + { + ""alg"": ""SHA256"", + ""e"": ""AQAB"", + ""key_ops"": [ + ""signing"" ], - ""userinfo_endpoint"": ""https://login.microsoftonline.com/add29489-7269-41f4-8841-b63c95564420/openid/userinfo"", - ""userinfo_encryption_alg_values_supported"": [ - ""ECDH-ES+A128KW"", - ""ECDH-ES+A192KW"" + ""kid"": ""NGTFvdK-fythEuLwjpwAJOM9n-A"", + ""kty"": ""RSA"", + ""n"": ""rCz8Sn3GGXmikH2MdTeGY1D711EORX/lVXpr+ecGgqfUWF8MPB07XkYuJ54DAuYT318+2XrzMjOtqkT94VkXmxv6dFGhG8YZ8vNMPd4tdj9c0lpvWQdqXtL1TlFRpD/P6UMEigfN0c9oWDg9U7Ilymgei0UXtf1gtcQbc5sSQU0S4vr9YJp2gLFIGK11Iqg4XSGdcI0QWLLkkC6cBukhVnd6BCYbLjTYy3fNs4DzNdemJlxGl8sLexFytBF6YApvSdus3nFXaMCtBGx16HzkK9ne3lobAwL2o79bP4imEGqg+ibvyNmbrwFGnQrBc1jTF9LyQX9q+louxVfHs6ZiVw=="", + ""use"": ""sig"", + ""x5c"": [ + ""MIIDPjCCAiqgAwIBAgIQVWmXY/+9RqFA/OG9kFulHDAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTIwNjA3MDcwMDAwWhcNMTQwNjA3MDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArCz8Sn3GGXmikH2MdTeGY1D711EORX/lVXpr+ecGgqfUWF8MPB07XkYuJ54DAuYT318+2XrzMjOtqkT94VkXmxv6dFGhG8YZ8vNMPd4tdj9c0lpvWQdqXtL1TlFRpD/P6UMEigfN0c9oWDg9U7Ilymgei0UXtf1gtcQbc5sSQU0S4vr9YJp2gLFIGK11Iqg4XSGdcI0QWLLkkC6cBukhVnd6BCYbLjTYy3fNs4DzNdemJlxGl8sLexFytBF6YApvSdus3nFXaMCtBGx16HzkK9ne3lobAwL2o79bP4imEGqg+ibvyNmbrwFGnQrBc1jTF9LyQX9q+louxVfHs6ZiVwIDAQABo2IwYDBeBgNVHQEEVzBVgBCxDDsLd8xkfOLKm4Q/SzjtoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQVWmXY/+9RqFA/OG9kFulHDAJBgUrDgMCHQUAA4IBAQAkJtxxm/ErgySlNk69+1odTMP8Oy6L0H17z7XGG3w4TqvTUSWaxD4hSFJ0e7mHLQLQD7oV/erACXwSZn2pMoZ89MBDjOMQA+e6QzGB7jmSzPTNmQgMLA8fWCfqPrz6zgH+1F1gNp8hJY57kfeVPBiyjuBmlTEBsBlzolY9dd/55qqfQk6cgSeCbHCy/RU/iep0+UsRMlSgPNNmqhj5gmN2AFVCN96zF694LwuPae5CeR2ZcVknexOWHYjFM0MgUSw0ubnGl0h9AJgGyhvNGcjQqu9vd1xkupFgaN+f7P3p3EVN5csBg5H94jEcQZT7EKeTiZ6bTrpDAnrr8tDCy8ng"" ], - ""userinfo_encryption_enc_values_supported"": [ - ""A256CBC-HS512"", - ""A128CBC-HS256"" + ""x5t"": ""NGTFvdK-fythEuLwjpwAJOM9n-A"", + ""x5u"": ""https://jsonkeyurl"" + }, + { + ""alg"": ""SHA256"", + ""e"": ""AQAB"", + ""kid"": ""kriMPdmBvx68skT8-mPAB3BseeA"", + ""kty"": ""RSA"", + ""n"": ""kSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuw=="", + ""use"": ""sig"", + ""x5c"": [ + ""MIIDPjCCAiqgAwIBAgIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTQwMTAxMDcwMDAwWhcNMTYwMTAxMDcwMDAwWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS/AHsBeQPqYygfYVJL6/EgzVuwRk5txr9e3n1uml94fLyq/AXbwo9yAduf4dCHTP8CWR1dnDR+Qnz/4PYlWVEuuHHONOw/blbfdMjhY+C/BYM2E3pRxbohBb3x//CfueV7ddz2LYiH3wjz0QS/7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd/GTgWN8A+6SN1r4hzpjFKFLbZnBt77ACSiYx+IHK4Mp+NaVEi5wQtSsjQtI++XsokxRDqYLwus1I1SihgbV/STTg5enufuwIDAQABo2IwYDBeBgNVHQEEVzBVgBDLebM6bK3BjWGqIBrBNFeNoS8wLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAA4IBAQCJ4JApryF77EKC4zF5bUaBLQHQ1PNtA1uMDbdNVGKCmSf8M65b8h0NwlIjGGGy/unK8P6jWFdm5IlZ0YPTOgzcRZguXDPj7ajyvlVEQ2K2ICvTYiRQqrOhEhZMSSZsTKXFVwNfW6ADDkN3bvVOVbtpty+nBY5UqnI7xbcoHLZ4wYD251uj5+lo13YLnsVrmQ16NCBYq2nQFNPuNJw6t3XUbwBHXpF46aLT1/eGf/7Xx6iy8yPJX4DyrpFTutDz882RWofGEO5t4Cw+zZg70dJ/hH/ODYRMorfXEW+8uKmXMKmX2wyxMKvfiPbTy5LmAU8Jvjs2tLg4rOBcXWLAIarZ"" ], - ""userinfo_signing_alg_values_supported"": [ - ""ES384"", - ""ES512"" - ] - }"; + ""x5t"": ""kriMPdmBvx68skT8-mPAB3BseeA"" + } + ], + ""scopes_supported"": [ + ""openid"" + ], + ""revocation_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/revocation"", + ""revocation_endpoint_auth_methods_supported"": [ + ""client_secret_post"", + ""client_secret_basic"" + ], + ""revocation_endpoint_auth_signing_alg_values_supported"": [ + ""ES192"", + ""ES256"" + ], + ""service_documentation"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/service_documentation"", + ""subject_types_supported"": [ + ""pairwise"" + ], + ""token_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/token"", + ""token_endpoint_auth_methods_supported"": [ + ""client_secret_post"", + ""private_key_jwt"" + ], + ""token_endpoint_auth_signing_alg_values_supported"": [ + ""ES192"", + ""ES256"" + ], + ""ui_locales_supported"": [ + ""hak-CN"", + ""en-us"" + ], + ""userinfo_endpoint"": ""https://login.microsoftonline.com/add29489-7269-41f4-8841-b63c95564420/openid/userinfo"", + ""userinfo_encryption_alg_values_supported"": [ + ""ECDH-ES+A128KW"", + ""ECDH-ES+A192KW"" + ], + ""userinfo_encryption_enc_values_supported"": [ + ""A256CBC-HS512"", + ""A128CBC-HS256"" + ], + ""userinfo_signing_alg_values_supported"": [ + ""ES384"", + ""ES512"" + ] + }"; public static string JsonAllValues = @"{ ""acr_values_supported"": [""acr_value1"", ""acr_value2"", ""acr_value3""], ""authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/authorize"", diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs index 2be8b56fb0..82e4c0a849 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectSerializationTests.cs @@ -42,6 +42,13 @@ public static TheoryData DesrializeTheoryData TheoryData theoryData = new TheoryData(); // the reason to replace AdditionalData with upper case is because the test deserializes uppercase and lowercase. // we wanted to leave the data sets in original form from discovery to be used in other tests. + + theoryData.Add(new OpenIdConnectTheoryData("SerializeJsonWebKeySet") + { + CompareTo = OpenIdConfigData.DefaultConfigWithJWK, + Json = OpenIdConfigData.JsonWithJWK + }); + theoryData.Add(new OpenIdConnectTheoryData("AADCommonV1") { CompareTo = JsonUtilities.SetAdditionalDataKeysToUpperCase(OpenIdConfigData.AADCommonV1Config), @@ -138,12 +145,6 @@ public static TheoryData DesrializeTheoryData Json = JsonData.NullObject }); - theoryData.Add(new OpenIdConnectTheoryData("SerializeJsonWebKeySet") - { - CompareTo = OpenIdConfigData.DefaultConfigWithJWK, - Json = OpenIdConfigData.JsonWithJWK - }); - return theoryData; } } From 39c3ac2419f4aa0380567b8cdeb19d70f4740ce1 Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Wed, 19 Jun 2024 18:15:56 +0100 Subject: [PATCH 09/12] Increase number of properties --- .../Json/OpenIdConnectConfigurationSerializer.cs | 2 +- .../ConfigurationManagerTests.cs | 4 ++-- .../EmptyJsonWebKeySet.json | 3 +++ ...crosoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj | 2 +- .../OpenIdConnectConfigurationTests.cs | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/EmptyJsonWebKeySet.json diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs index 0a14496e7e..f5c9d732d6 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs @@ -824,7 +824,7 @@ public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration c if (config.UserInfoEndpointSigningAlgValuesSupported.Count > 0) JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.UserInfoSigningAlgValuesSupported, config.UserInfoEndpointSigningAlgValuesSupported); - + if (config.AdditionalData.Count > 0) JsonPrimitives.WriteObjects(ref writer, config.AdditionalData); diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs index d461b07b8c..382daaa3b7 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs @@ -634,7 +634,7 @@ public static TheoryData - + PreserveNewest diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs index c86c4c417e..8922ac804a 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs @@ -162,8 +162,8 @@ public void GetSets() OpenIdConnectConfiguration configuration = new OpenIdConnectConfiguration(); Type type = typeof(OpenIdConnectConfiguration); PropertyInfo[] properties = type.GetProperties(); - if (properties.Length != 67) - Assert.True(false, "Number of properties has changed from 67 to: " + properties.Length + ", adjust tests"); + if (properties.Length != 68) + Assert.True(false, "Number of properties has changed from 68 to: " + properties.Length + ", adjust tests"); TestUtilities.CallAllPublicInstanceAndStaticPropertyGets(configuration, "OpenIdConnectConfiguration_GetSets"); From a783b21ba68bd9da3a5360254c82f5cf85b09f6d Mon Sep 17 00:00:00 2001 From: "REDMOND\\nguyencuong" Date: Thu, 20 Jun 2024 17:26:26 +0100 Subject: [PATCH 10/12] Add new props to mock data --- .../OpenIdConfigData.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs index db81001567..9eb4cb55bf 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs @@ -83,6 +83,18 @@ public static OpenIdConnectConfiguration FullyPopulatedWithKeys ""acr_value3"" ], ""authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/authorize"", + ""authorization_encryption_alg_values_supported"": [ + ""A192KW"", + ""A256KW"" + ], + ""authorization_encryption_enc_values_supported"": [ + ""A128CBC-HS256"", + ""A256CBC-HS512"" + ], + ""authorization_signing_alg_values_supported"": [ + ""ES384"", + ""ES512"" + ], ""backchannel_authentication_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/bc-authorize"", ""backchannel_authentication_request_signing_alg_values_supported"": [ ""ES384"", @@ -252,6 +264,7 @@ public static OpenIdConnectConfiguration FullyPopulatedWithKeys ""ES192"", ""ES256"" ], + ""tls_client_certificate_bound_access_tokens"": true, ""ui_locales_supported"": [ ""hak-CN"", ""en-us"" From 53d0d528a4d61d7807ac43ef208f429f19927bdb Mon Sep 17 00:00:00 2001 From: nguyencuong2596 <164532638+nguyencuong2596@users.noreply.github.com> Date: Thu, 20 Jun 2024 18:29:51 +0100 Subject: [PATCH 11/12] Add Append to JWK Serializer --- .../Json/OpenIdConnectConfigurationSerializer.cs | 2 +- .../Json/JsonWebKeySetSerializer.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs index f5c9d732d6..d49e97aecb 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs @@ -778,7 +778,7 @@ public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration c JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ResponseTypesSupported, config.ResponseTypesSupported); if (config.ShouldSerializeJsonWebKeys && config.JsonWebKeySet != null && config.JsonWebKeySet.Keys.Count > 0) - JsonWebKeySetSerializer.Write(ref writer, config.JsonWebKeySet, shouldWriteObject: false); + JsonWebKeySetSerializer.Append(ref writer, config.JsonWebKeySet); if (config.ScopesSupported.Count > 0) JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ScopesSupported, config.ScopesSupported); diff --git a/src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySetSerializer.cs b/src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySetSerializer.cs index 5b1ef6f6bd..42ec2dc7bd 100644 --- a/src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySetSerializer.cs +++ b/src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySetSerializer.cs @@ -136,12 +136,15 @@ public static string Write(JsonWebKeySet jsonWebKeySet) /// /// /// - /// - public static void Write(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet, bool shouldWriteObject = true) + public static void Write(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet) { - if (shouldWriteObject) - writer.WriteStartObject(); + writer.WriteStartObject(); + Append(ref writer, jsonWebKeySet); + writer.WriteEndObject(); + } + internal static void Append(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet) + { writer.WritePropertyName(JsonWebKeyParameterUtf8Bytes.Keys); writer.WriteStartArray(); @@ -152,9 +155,6 @@ public static void Write(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet, if (jsonWebKeySet.AdditionalData.Count > 0) JsonSerializerPrimitives.WriteObjects(ref writer, jsonWebKeySet.AdditionalData); - - if (shouldWriteObject) - writer.WriteEndObject(); } #endregion From 82405383fa640ae49f37da665b1b1ffd54e30401 Mon Sep 17 00:00:00 2001 From: nguyencuong2596 <164532638+nguyencuong2596@users.noreply.github.com> Date: Thu, 20 Jun 2024 18:47:24 +0100 Subject: [PATCH 12/12] Remove debug code --- .../Json/OpenIdConnectConfigurationSerializer.cs | 2 -- .../OpenIdConfigData.cs | 1 - 2 files changed, 3 deletions(-) diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs index d49e97aecb..74224a0c6b 100644 --- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs +++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs @@ -225,7 +225,6 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (reader.ValueTextEquals(Encoding.UTF8.GetBytes(JsonWebKeySetParameterNames.Keys))) { - config.ShouldSerializeJsonWebKeys = true; if (config.JsonWebKeySet == null) config.JsonWebKeySet = new JsonWebKeySet(); // Skip key "Keys" @@ -591,7 +590,6 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC else if (propertyName.Equals(JsonWebKeySetParameterNames.Keys, StringComparison.OrdinalIgnoreCase)) { - config.ShouldSerializeJsonWebKeys = true; if (config.JsonWebKeySet == null) config.JsonWebKeySet = new JsonWebKeySet(); // Skip key "Keys" diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs index 9eb4cb55bf..16ac7bce04 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs @@ -23,7 +23,6 @@ public static OpenIdConnectConfiguration DefaultConfigWithJWK { var config = Default; config.JsonWebKeySet = DataSets.JsonWebKeySet1; - config.ShouldSerializeJsonWebKeys = true; return config; } }