From 650e55d6442009cb9b2599fb041867a202a71188 Mon Sep 17 00:00:00 2001 From: Brent Schmaltz Date: Fri, 8 Sep 2023 12:29:18 -0700 Subject: [PATCH] Support 6x where JsonWebToken.GetPayloadValue("aud") Throws if multiple audiences exist. --- .../Json/JsonClaimSet.cs | 8 ++- .../GetPayloadValueTheoryData.cs | 5 +- .../JsonWebTokenTests.cs | 61 ++++++++++++++++++- 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs b/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs index 1bfd9132b2..3e68c04c6b 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs @@ -216,7 +216,13 @@ internal T GetValue(string key, bool throwEx, out bool found) if (objType == typeof(DateTime)) return (T)((object)((DateTime)obj).ToString("o", CultureInfo.InvariantCulture)); - return (T)((object)obj.ToString()); + if (obj is List list) + { + if (list.Count == 1) + return (T)((object)(list[0])); + } + else + return (T)((object)obj.ToString()); } else if (typeof(T) == typeof(bool)) { diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/GetPayloadValueTheoryData.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/GetPayloadValueTheoryData.cs index 4793da6a51..3447ca0d8e 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/GetPayloadValueTheoryData.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/GetPayloadValueTheoryData.cs @@ -3,7 +3,6 @@ using System; using Microsoft.IdentityModel.TestUtils; -using Microsoft.IdentityModel.Tokens; namespace Microsoft.IdentityModel.JsonWebTokens.Tests { @@ -12,12 +11,10 @@ public class GetPayloadValueTheoryData : TheoryDataBase public GetPayloadValueTheoryData(string testId) : base(testId) { } - public SecurityTokenDescriptor SecurityTokenDescriptor { get; set; } + public object ClaimValue { get; set; } public string PropertyName { get; set; } - public Type PropertyOut { get; set; } - public Type PropertyType { get; set; } public object PropertyValue { get; set; } diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenTests.cs index d160b12d74..c041edc187 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenTests.cs @@ -247,7 +247,19 @@ public void CheckAudienceValues(GetPayloadValueTheoryData theoryData) try { JsonWebToken jsonWebToken = new JsonWebToken(theoryData.Json); - IdentityComparer.AreEqual(jsonWebToken.Audiences, theoryData.PropertyValue, context); + MethodInfo method = typeof(JsonWebToken).GetMethod("GetPayloadValue"); + MethodInfo generic = method.MakeGenericMethod(theoryData.PropertyType); + object[] parameters = new object[] { theoryData.PropertyName }; + var audiences = generic.Invoke(jsonWebToken, parameters); + + if (!IdentityComparer.AreEqual(jsonWebToken.Audiences, theoryData.PropertyValue, context)) + context.AddDiff($"jsonWebToken.Audiences != theoryData.PropertyValue: '{jsonWebToken.Audiences}' != '{theoryData.PropertyValue}'."); + + if (theoryData.ClaimValue != null) + if (!IdentityComparer.AreEqual(audiences, theoryData.ClaimValue, context)) + context.AddDiff($"audiences != theoryData.ClaimValue: '{audiences}' != '{theoryData.ClaimValue}'."); + + theoryData.ExpectedException.ProcessNoException(context); } catch (Exception ex) { @@ -263,31 +275,76 @@ public static TheoryData CheckAudienceValuesTheoryDat { var theoryData = new TheoryData(); + theoryData.Add(new GetPayloadValueTheoryData("stringFromSingleInList") + { + ClaimValue = "audience", + PropertyName = "aud", + PropertyType = typeof(string), + PropertyValue = new List { "audience" }, + Json = JsonUtilities.CreateUnsignedToken("aud", new List { "audience" }) + }); + + theoryData.Add(new GetPayloadValueTheoryData("stringFromMultipeInList") + { + ClaimValue = "audience", + ExpectedException = ExpectedException.ArgumentException("IDX14305:"), + PropertyName = "aud", + PropertyValue = new List { "audience", "audience2" }, + PropertyType = typeof(string), + Json = JsonUtilities.CreateUnsignedToken("aud", new List { "audience", "audience2" }) + }); + + theoryData.Add(new GetPayloadValueTheoryData("stringTwoNulloneNonNull") + { + ClaimValue = "audience1", + PropertyName = "aud", + PropertyValue = new List { "audience1" }, + PropertyType = typeof(string), + Json = JsonUtilities.CreateUnsignedToken("aud", new List { null, "audience1", null }) + }); + + theoryData.Add(new GetPayloadValueTheoryData("stringFromCollection") + { + ClaimValue = "audience", + PropertyName = "aud", + PropertyType = typeof(string), + PropertyValue = new Collection { "audience" }, + Json = JsonUtilities.CreateUnsignedToken("aud", new Collection { "audience" }) + }); + theoryData.Add(new GetPayloadValueTheoryData("singleNull") { + ClaimValue = new List(), PropertyName = "aud", PropertyValue = new List(), + PropertyType = typeof(List), Json = JsonUtilities.CreateUnsignedToken("aud", null) }); theoryData.Add(new GetPayloadValueTheoryData("twoNull") { + ClaimValue = new List(), PropertyName = "aud", PropertyValue = new List(), + PropertyType = typeof(List), Json = JsonUtilities.CreateUnsignedToken("aud", new List{ null, null }) }); theoryData.Add(new GetPayloadValueTheoryData("singleNonNull") { + ClaimValue = new List { "audience" }, PropertyName = "aud", PropertyValue = new List { "audience"}, + PropertyType = typeof(List), Json = JsonUtilities.CreateUnsignedToken("aud", "audience") }); theoryData.Add(new GetPayloadValueTheoryData("twoNulloneNonNull") { + ClaimValue = new List { "audience1" }, PropertyName = "aud", PropertyValue = new List { "audience1"}, + PropertyType = typeof(List), Json = JsonUtilities.CreateUnsignedToken("aud", new List { null, "audience1", null }) }); @@ -540,7 +597,7 @@ public static TheoryData GetPayloadValueTheoryData }); #endregion - #region collection of strings form simple types + #region collection of strings from simple types #region string[] theoryData.Add(new GetPayloadValueTheoryData("string[]dateTime")