From 6aa3efd2130a4e71090d1e74dbd15aa4ebd3d1b0 Mon Sep 17 00:00:00 2001 From: Xiao Zhang <85274586+ciaozhang@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:20:13 -0800 Subject: [PATCH] Xiao/Enrich metadata failure message during metadata refresh interval (#2010) * Enrich exception during metadata refresh interval --- .../Configuration/ConfigurationManager.cs | 4 ++- .../ConfigurationManagerTests.cs | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 8cd2aa4fe1..d737734b88 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -27,6 +27,7 @@ public class ConfigurationManager : BaseConfigurationManager, IConfigurationM private readonly IConfigurationRetriever _configRetriever; private readonly IConfigurationValidator _configValidator; private T _currentConfiguration; + private Exception _fetchMetadataFailure; /// /// Static initializer for a new object. Static initializers run before the first instance of the type is created. @@ -148,6 +149,7 @@ public async Task GetConfigurationAsync(CancellationToken cancel) } catch (Exception ex) { + _fetchMetadataFailure = ex; _syncAfter = DateTimeUtil.Add(now.UtcDateTime, AutomaticRefreshInterval < RefreshInterval ? AutomaticRefreshInterval : RefreshInterval); if (_currentConfiguration == null) // Throw an exception if there's no configuration to return. throw LogHelper.LogExceptionMessage( @@ -166,7 +168,7 @@ public async Task GetConfigurationAsync(CancellationToken cancel) else throw LogHelper.LogExceptionMessage( new InvalidOperationException( - LogHelper.FormatInvariant(LogMessages.IDX20803, LogHelper.MarkAsNonPII(MetadataAddress ?? "null")))); + LogHelper.FormatInvariant(LogMessages.IDX20803, LogHelper.MarkAsNonPII(MetadataAddress ?? "null"), LogHelper.MarkAsNonPII(_fetchMetadataFailure)), _fetchMetadataFailure)); } finally { diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs index 17ab65575a..f1627eb53f 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTests.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics.Tracing; using System.IO; +using System.Net; using System.Reflection; using System.Threading; using Microsoft.IdentityModel.Protocols.OpenIdConnect.Configuration; @@ -100,6 +101,41 @@ public void Defaults() Assert.Equal(ConfigurationManager.MinimumRefreshInterval, new TimeSpan(0, 0, 0, 1)); } + [Fact] + public void FetchMetadataFailureTest() + { + var context = new CompareContext($"{this}.FetchMetadataFailureTest"); + + var documentRetriever = new HttpDocumentRetriever(HttpResponseMessageUtils.SetupHttpClientThatReturns("OpenIdConnectMetadata.json", HttpStatusCode.NotFound)); + var configManager = new ConfigurationManager("OpenIdConnectMetadata.json", new OpenIdConnectConfigurationRetriever(), documentRetriever); + + // First time to fetch metadata + try + { + var configuration = configManager.GetConfigurationAsync().Result; + } + catch (Exception firstFetchMetadataFailure) + { + if (firstFetchMetadataFailure.InnerException == null) + context.AddDiff($"Expected exception to contain inner exception for fetch metadata failure."); + + // Fetch metadata again during refresh interval, the exception should be same from above + try + { + var configuration = configManager.GetConfigurationAsync().Result; + } + catch (Exception secondFetchMetadataFailure) + { + if (secondFetchMetadataFailure.InnerException == null) + context.AddDiff($"Expected exception to contain inner exception for fetch metadata failure."); + + IdentityComparer.AreEqual(firstFetchMetadataFailure, secondFetchMetadataFailure, context); + } + } + + TestUtilities.AssertFailIfErrors(context); + } + [Fact] public void GetSets() {