Skip to content

Commit 675a7fc

Browse files
Brent Schmaltzbrentschmaltz
authored andcommitted
reverted to skipping audiences strings that are null
1 parent 76aa676 commit 675a7fc

File tree

3 files changed

+94
-2
lines changed

3 files changed

+94
-2
lines changed

src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonWebToken.PayloadClaimSet.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ internal JsonClaimSet CreatePayloadClaimSet(byte[] bytes, int length)
3838
reader.Read();
3939
if (reader.TokenType == JsonTokenType.StartArray)
4040
{
41-
JsonSerializerPrimitives.ReadStrings(ref reader, _audiences, JwtRegisteredClaimNames.Aud, ClassName, false);
41+
JsonSerializerPrimitives.ReadStringsSkipNulls(ref reader, _audiences, JwtRegisteredClaimNames.Aud, ClassName);
4242
claims[JwtRegisteredClaimNames.Aud] = _audiences;
4343
}
4444
else
4545
{
46-
_audiences.Add(JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Aud, ClassName, false));
46+
if (reader.TokenType != JsonTokenType.Null)
47+
_audiences.Add(JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Aud, ClassName));
48+
4749
claims[JwtRegisteredClaimNames.Aud] = _audiences;
4850
}
4951
}

src/Microsoft.IdentityModel.Tokens/Json/JsonSerializerPrimitives.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,34 @@ internal static IList<string> ReadStrings(
741741
return strings;
742742
}
743743

744+
// This is a special case for reading audiences where in 6x, we didn't add null strings to the list.
745+
internal static void ReadStringsSkipNulls(
746+
ref Utf8JsonReader reader,
747+
List<string> strings,
748+
string propertyName,
749+
string className)
750+
{
751+
if (reader.TokenType == JsonTokenType.Null)
752+
return;
753+
754+
if (!IsReaderAtTokenType(ref reader, JsonTokenType.StartArray, false))
755+
throw LogHelper.LogExceptionMessage(
756+
CreateJsonReaderExceptionInvalidType(ref reader, "JsonTokenType.StartArray", className, propertyName));
757+
758+
while (reader.Read())
759+
{
760+
if (IsReaderAtTokenType(ref reader, JsonTokenType.EndArray, false))
761+
break;
762+
763+
if (reader.TokenType == JsonTokenType.Null)
764+
continue;
765+
766+
strings.Add(ReadString(ref reader, propertyName, className));
767+
}
768+
769+
return;
770+
}
771+
744772
/// <summary>
745773
/// This method is called when deserializing a property value as an object.
746774
/// Normally we put the object into a Dictionary[string, object].
@@ -909,6 +937,12 @@ public static void WriteObjectValue(ref Utf8JsonWriter writer, object obj)
909937
LogHelper.MarkAsNonPII(writer.CurrentDepth),
910938
LogHelper.MarkAsNonPII(MaxDepth)));
911939

940+
if (obj is null)
941+
{
942+
writer.WriteNullValue();
943+
return;
944+
}
945+
912946
Type objType = obj.GetType();
913947

914948
if (obj is string str)

test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenTests.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,62 @@ public void CompareJwtSecurityTokenWithJsonSecurityTokenMultipleAudiences()
239239
TestUtilities.AssertFailIfErrors(context);
240240
}
241241

242+
// This test ensures audience values are skipping nulls as expected.
243+
[Theory, MemberData(nameof(CheckAudienceValuesTheoryData), DisableDiscoveryEnumeration = true)]
244+
public void CheckAudienceValues(GetPayloadValueTheoryData theoryData)
245+
{
246+
CompareContext context = TestUtilities.WriteHeader($"{this}.CheckAudienceValues", theoryData);
247+
try
248+
{
249+
JsonWebToken jsonWebToken = new JsonWebToken(theoryData.Json);
250+
IdentityComparer.AreEqual(jsonWebToken.Audiences, theoryData.PropertyValue, context);
251+
}
252+
catch (Exception ex)
253+
{
254+
theoryData.ExpectedException.ProcessException(ex.InnerException, context);
255+
}
256+
257+
TestUtilities.AssertFailIfErrors(context);
258+
}
259+
260+
public static TheoryData<GetPayloadValueTheoryData> CheckAudienceValuesTheoryData
261+
{
262+
get
263+
{
264+
var theoryData = new TheoryData<GetPayloadValueTheoryData>();
265+
266+
theoryData.Add(new GetPayloadValueTheoryData("singleNull")
267+
{
268+
PropertyName = "aud",
269+
PropertyValue = new List<string>(),
270+
Json = JsonUtilities.CreateUnsignedToken("aud", null)
271+
});
272+
273+
theoryData.Add(new GetPayloadValueTheoryData("twoNull")
274+
{
275+
PropertyName = "aud",
276+
PropertyValue = new List<string>(),
277+
Json = JsonUtilities.CreateUnsignedToken("aud", new List<string>{ null, null })
278+
});
279+
280+
theoryData.Add(new GetPayloadValueTheoryData("singleNonNull")
281+
{
282+
PropertyName = "aud",
283+
PropertyValue = new List<string> { "audience"},
284+
Json = JsonUtilities.CreateUnsignedToken("aud", "audience")
285+
});
286+
287+
theoryData.Add(new GetPayloadValueTheoryData("twoNulloneNonNull")
288+
{
289+
PropertyName = "aud",
290+
PropertyValue = new List<string> { "audience1"},
291+
Json = JsonUtilities.CreateUnsignedToken("aud", new List<string> { null, "audience1", null })
292+
});
293+
294+
return theoryData;
295+
}
296+
}
297+
242298
// This test ensures that TryGetPayloadValue does not throw
243299
// No need to check for equal as GetPayloadValue does that
244300
[Theory, MemberData(nameof(GetPayloadValueTheoryData), DisableDiscoveryEnumeration = true)]

0 commit comments

Comments
 (0)