diff --git a/src/Microsoft.IdentityModel.Tokens/BaseConfigurationComparer.cs b/src/Microsoft.IdentityModel.Tokens/BaseConfigurationComparer.cs index b4578d9ec8..8253a9d681 100644 --- a/src/Microsoft.IdentityModel.Tokens/BaseConfigurationComparer.cs +++ b/src/Microsoft.IdentityModel.Tokens/BaseConfigurationComparer.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System.Collections.Generic; -using System.Linq; namespace Microsoft.IdentityModel.Tokens { @@ -17,11 +16,22 @@ public bool Equals(BaseConfiguration config1, BaseConfiguration config2) return true; else if (config1 == null || config2 == null) return false; - else if (config1.Issuer == config2.Issuer && config1.SigningKeys.Count == config2.SigningKeys.Count - && !config1.SigningKeys.Select(x => x.InternalId).Except(config2.SigningKeys.Select(x => x.InternalId)).Any()) - return true; else - return false; + { + if (config1.Issuer != config2.Issuer) + return false; + + if (config1.SigningKeys.Count != config2.SigningKeys.Count) + return false; + + foreach (var key in config1.SigningKeys) + { + if (!config2.SigningKeys.Contains(key)) + return false; + } + } + + return true; } public int GetHashCode(BaseConfiguration config) @@ -29,10 +39,9 @@ public int GetHashCode(BaseConfiguration config) int defaultHash = string.Empty.GetHashCode(); int hashCode = defaultHash; hashCode ^= string.IsNullOrEmpty(config.Issuer) ? defaultHash : config.Issuer.GetHashCode(); - foreach(string internalId in config.SigningKeys.Select(x => x.InternalId)) - { - hashCode ^= internalId.GetHashCode(); - } + + foreach (var key in config.SigningKeys) + hashCode ^= key.InternalId.GetHashCode(); return hashCode; } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/BaseConfigurationComparerTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/BaseConfigurationComparerTests.cs new file mode 100644 index 0000000000..57d19ad485 --- /dev/null +++ b/test/Microsoft.IdentityModel.Tokens.Tests/BaseConfigurationComparerTests.cs @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.IdentityModel.TestUtils; +using Xunit; + +namespace Microsoft.IdentityModel.Tokens.Tests +{ + public class BaseConfigurationComparerTests + { + [Theory, MemberData(nameof(ComparerTheoryData))] + public void Compare(BaseConfigurationComparerTheoryData theoryData) + { + var context = TestUtilities.WriteHeader($"{this}.Compare", theoryData); + var comparer = new BaseConfigurationComparer(); + var result = comparer.Equals(theoryData.ConfigurationA, theoryData.ConfigurationB); + Assert.Equal(theoryData.ShouldBeEqual, result); + } + + public static TheoryData ComparerTheoryData() + { + var jsonWebKey1 = new TestConfiguration + { + Issuer = "http://example.com/issuer/1", + }; + + jsonWebKey1.SigningKeys.Add(DataSets.JsonWebKey1); + + var jsonWebKey2 = new TestConfiguration + { + Issuer = "http://example.com/issuer/1", + }; + + var bothJsonWebKeys = new TestConfiguration + { + Issuer = "http://example.com/issuer/1", + }; + + bothJsonWebKeys.SigningKeys.Add(DataSets.JsonWebKey1); + bothJsonWebKeys.SigningKeys.Add(DataSets.JsonWebKey2); + + jsonWebKey1.SigningKeys.Add(DataSets.JsonWebKey2); + + return new TheoryData() + { + new() + { + TestId = "Both null", + ConfigurationA = null, + ConfigurationB = null, + ShouldBeEqual = true, + }, + new() + { + TestId = "B null", + ConfigurationA = new TestConfiguration(), + ConfigurationB = null, + ShouldBeEqual = false, + }, + new() + { + TestId = "A null", + ConfigurationA = null, + ConfigurationB = new TestConfiguration(), + ShouldBeEqual = false, + }, + new() + { + TestId = "Issuer mismatched", + ConfigurationA = new TestConfiguration + { + Issuer = "http://example.com/issuer/1" + }, + ConfigurationB = new TestConfiguration + { + Issuer = "http://example.com/issuer/2" + }, + ShouldBeEqual = false, + }, + new() + { + TestId = "No Keys", + ConfigurationA = new TestConfiguration + { + Issuer = "http://example.com/issuer/1", + }, + ConfigurationB = new TestConfiguration + { + Issuer = "http://example.com/issuer/1" + }, + ShouldBeEqual = true, + }, + new() + { + TestId = "different keys", + ConfigurationA = jsonWebKey1, + ConfigurationB = jsonWebKey2, + ShouldBeEqual = false, + }, + new() + { + TestId = "same keys", + ConfigurationA = jsonWebKey1, + ConfigurationB = jsonWebKey1, + ShouldBeEqual = true, + }, + new () + { + TestId = "different number of keys", + ConfigurationA = jsonWebKey1, + ConfigurationB = bothJsonWebKeys, + ShouldBeEqual = false, + }, + }; + } + } + + public class BaseConfigurationComparerTheoryData : TheoryDataBase + { + public BaseConfiguration ConfigurationA { get; set; } + + public BaseConfiguration ConfigurationB { get; set; } + + public bool ShouldBeEqual { get; set; } + } + + public class TestConfiguration : BaseConfiguration + { + } +}