Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Add Serialization for JsonWebToken in OpenIdConnectConfiguration #2627

Closed
wants to merge 14 commits into from
Closed
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,13 @@ public bool ShouldSerializeUserInfoEndpointSigningAlgValuesSupported()
{
return UserInfoEndpointSigningAlgValuesSupported.Count > 0;
}
#endregion shouldserialize

/// <summary>
/// Gets or sets a value indicating whether the JsonWebKeys should be serialized.
/// </summary>
[JsonIgnore]
public bool ShouldSerializeJsonWebKeys { get; set; }

#endregion shouldserialize
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,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
{
Expand Down Expand Up @@ -69,6 +71,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",
Expand Down Expand Up @@ -220,6 +223,16 @@ 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)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenIdConnectRetriever will reset the JsonWebKeySet here:

Is that accounted for?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. However, this shouldn't disrupt the flow that retrieves the configuration from an L2 cache. It might be best to fetch keys only if they are not already set.

{
config.ShouldSerializeJsonWebKeys = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this set to true?

if (config.JsonWebKeySet == null)
config.JsonWebKeySet = new JsonWebKeySet();
// Skip key "Keys"
reader.Read();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is different than the case-insensitive below, reader.Read() is not called.

JsonWebKeySetSerializer.ReadKeys(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))
Expand Down Expand Up @@ -575,6 +588,15 @@ 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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking behavior for users.
Previously, users would have found an object in AdditionalData.

{
config.ShouldSerializeJsonWebKeys = true;
if (config.JsonWebKeySet == null)
config.JsonWebKeySet = new JsonWebKeySet();
// Skip key "Keys"
JsonWebKeySetSerializer.ReadKeys(ref reader, config.JsonWebKeySet);
}
}
#endregion case-insensitive
}
Expand Down Expand Up @@ -755,6 +777,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.Append(ref writer, config.JsonWebKeySet);

if (config.ScopesSupported.Count > 0)
JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.ScopesSupported, config.ScopesSupported);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,12 @@ public static string Write(JsonWebKeySet jsonWebKeySet)
public static void Write(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet)
{
writer.WriteStartObject();
Append(ref writer, jsonWebKeySet);
writer.WriteEndObject();
}

internal static void Append(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WriteKeys would be a better name than Append.

{
writer.WritePropertyName(JsonWebKeyParameterUtf8Bytes.Keys);
writer.WriteStartArray();

Expand All @@ -150,8 +155,6 @@ public static void Write(ref Utf8JsonWriter writer, JsonWebKeySet jsonWebKeySet)

if (jsonWebKeySet.AdditionalData.Count > 0)
JsonSerializerPrimitives.WriteObjects(ref writer, jsonWebKeySet.AdditionalData);

writer.WriteEndObject();
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ public static TheoryData<ConfigurationManagerTheoryData<OpenIdConnectConfigurati
ConfigurationValidator = openIdConnectConfigurationValidator2,
DocumentRetriever = new FileDocumentRetriever(),
ExpectedException = new ExpectedException(typeof(InvalidOperationException), "IDX21817:", typeof(InvalidConfigurationException)),
MetadataAddress = "JsonWebKeySetUnrecognizedKty.json",
MetadataAddress = "EmptyJsonWebKeySet.json",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why were these tests removed?
JsonWebKeySetUnrecognizedKty

TestId = "InvalidConfiguration_EmptyJsonWenKeySet"
});

Expand All @@ -645,7 +645,7 @@ public static TheoryData<ConfigurationManagerTheoryData<OpenIdConnectConfigurati
DocumentRetriever = new FileDocumentRetriever(),
PresetCurrentConfiguration = true,
ExpectedErrorMessage = "IDX21817: ",
MetadataAddress = "JsonWebKeySetUnrecognizedKty.json",
MetadataAddress = "EmptyJsonWebKeySet.json",
TestId = "InvalidConfiguration_EmptyJsonWenKeySet_PresetCurrentConfiguration"
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"keys": []
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>

<ItemGroup>
<None Update="JsonWebKeySet.json;JsonWebKeySetBadBase64Data.json;JsonWebKeySetBadX509Data.json;JsonWebKeySetEnd2End.json;JsonWebKeySetSingleX509Data.json;OpenIdConnectMetadata.json;OpenIdConnectMetadata2.json;JsonWebKeySetUnrecognizedKty.json;JsonWebKeySetBadRsaDataMissingComponent.json;OpenIdConnectMetadataBadBase64Data.json;OpenIdConnectMetadataBadX509Data.json;OpenIdConnectMetadataEnd2End.json;OpenIdConnectMetadataJsonWebKeySetBadUri.json;PingLabsJWKS.json;PingLabs-openid-configuration.json;;JsonWebKeySetEnd2EndEC.json;OpenIdConnectMetadataEnd2EndEC.json;OpenIdConnectMetadataUnrecognizedKty.json;OpenIdConnectMetadataBadRsaDataMissingComponent.json">
<None Update="JsonWebKeySet.json;JsonWebKeySetBadBase64Data.json;JsonWebKeySetBadX509Data.json;JsonWebKeySetEnd2End.json;JsonWebKeySetSingleX509Data.json;OpenIdConnectMetadata.json;OpenIdConnectMetadata2.json;JsonWebKeySetUnrecognizedKty.json;JsonWebKeySetBadRsaDataMissingComponent.json;OpenIdConnectMetadataBadBase64Data.json;OpenIdConnectMetadataBadX509Data.json;OpenIdConnectMetadataEnd2End.json;OpenIdConnectMetadataJsonWebKeySetBadUri.json;PingLabsJWKS.json;PingLabs-openid-configuration.json;;JsonWebKeySetEnd2EndEC.json;OpenIdConnectMetadataEnd2EndEC.json;OpenIdConnectMetadataUnrecognizedKty.json;OpenIdConnectMetadataBadRsaDataMissingComponent.json;EmptyJsonWebKeySet.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Expand Down
Loading