Skip to content

Commit 107e31b

Browse files
committed
fix for 3021 but needs another test
1 parent d586c51 commit 107e31b

File tree

4 files changed

+99
-4
lines changed

4 files changed

+99
-4
lines changed

src/Microsoft.Identity.Web.Certificate/DefaultCredentialsLoader.Logger.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,19 @@ private static class Logger
2323
nameof(CredentialLoadingFailure)),
2424
"Failed to load credential {id} from source {sourceType}. Will it be skipped in the future ? {skip}.");
2525

26+
private static readonly Action<ILogger, string, string, Exception?> s_credentialLoadingFailureLog =
27+
LoggerMessage.Define<string, string>(
28+
LogLevel.Information,
29+
new EventId(
30+
8,
31+
nameof(CredentialLoadingFailureLog)),
32+
"Failed to load credential: {id}. Exception message: {message}. ");
33+
2634
public static void CredentialLoadingFailure(ILogger logger, CredentialDescription cd, Exception? ex)
2735
=> s_credentialLoadingFailure(logger, cd.Id, cd.SourceType.ToString(), cd.Skip, ex);
36+
37+
public static void CredentialLoadingFailureLog(ILogger logger, CredentialDescription cd, string message, Exception? ex)
38+
=> s_credentialLoadingFailureLog(logger, cd.Id, message, ex);
2839
}
2940
}
3041
}

src/Microsoft.Identity.Web.Certificate/DefaultCredentialsLoader.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,20 @@ public async Task LoadCredentialsIfNeededAsync(CredentialDescription credentialD
9797
/// <inheritdoc/>
9898
/// Loads first valid credential which is not marked as Skipped.
9999
public async Task<CredentialDescription?> LoadFirstValidCredentialsAsync(
100-
IEnumerable<CredentialDescription> credentialDescriptions,
100+
IEnumerable<CredentialDescription> credentialDescriptions,
101101
CredentialSourceLoaderParameters? parameters = null)
102102
{
103103
foreach (var credentialDescription in credentialDescriptions)
104104
{
105-
await LoadCredentialsIfNeededAsync(credentialDescription, parameters);
106-
107-
if (!credentialDescription.Skip)
105+
try
108106
{
107+
await LoadCredentialsIfNeededAsync(credentialDescription, parameters);
109108
return credentialDescription;
110109
}
110+
catch (Exception ex)
111+
{
112+
Logger.CredentialLoadingFailureLog(_logger, credentialDescription, ex.Message, null);
113+
}
111114
}
112115
return null;
113116
}

tests/Microsoft.Identity.Web.Test/Certificates/DefaultCertificateLoaderTests.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.Linq;
67
using System.Security.Cryptography.X509Certificates;
8+
using System.Threading.Tasks;
9+
using Microsoft.Extensions.Logging;
10+
using Microsoft.Identity.Abstractions;
711
using Microsoft.Identity.Web.Test.Common;
12+
using Moq;
813
using Xunit;
914

1015
namespace Microsoft.Identity.Web.Test.Certificates
@@ -152,5 +157,80 @@ private IEnumerable<CertificateDescription> CreateCertificateDescriptions(
152157

153158
return certificateDescription;
154159
}
160+
161+
[Fact]
162+
public async Task LoadFirstValidCredentialsAsync_ReturnsFirstValidCredential()
163+
{
164+
// Arrange
165+
var loggerMock = new Mock<ILogger<DefaultCredentialsLoader>>();
166+
var credentialLoader = new DefaultCredentialsLoader(loggerMock.Object);
167+
168+
var validCredential = new CredentialDescription
169+
{
170+
SourceType = CredentialSource.Path,
171+
ReferenceOrValue = "ValidCredential"
172+
};
173+
var invalidCredential = new CredentialDescription
174+
{
175+
SourceType = CredentialSource.Path,
176+
ReferenceOrValue = "InvalidCredential"
177+
};
178+
179+
var credentials = new List<CredentialDescription> { invalidCredential, validCredential };
180+
181+
var credentialSourceLoaderMock = new Mock<ICredentialSourceLoader>();
182+
credentialSourceLoaderMock
183+
.Setup(loader => loader.LoadIfNeededAsync(
184+
It.Is<CredentialDescription>(c => c.ReferenceOrValue == "InvalidCredential"), null))
185+
.ThrowsAsync(new Exception("Loading failed"));
186+
credentialSourceLoaderMock
187+
.Setup(loader => loader.LoadIfNeededAsync(
188+
It.Is<CredentialDescription>(c => c.ReferenceOrValue == "ValidCredential"), null))
189+
.Returns(Task.CompletedTask);
190+
191+
credentialLoader.CredentialSourceLoaders[CredentialSource.Path] = credentialSourceLoaderMock.Object;
192+
193+
// Act
194+
var result = await credentialLoader.LoadFirstValidCredentialsAsync(credentials);
195+
196+
// Assert
197+
Assert.NotNull(result);
198+
Assert.Equal(validCredential, result);
199+
credentialSourceLoaderMock.Verify(
200+
loader => loader.LoadIfNeededAsync(invalidCredential, null), Times.Once);
201+
credentialSourceLoaderMock.Verify(
202+
loader => loader.LoadIfNeededAsync(validCredential, null), Times.Once);
203+
}
204+
205+
[Fact]
206+
public async Task LoadFirstValidCredentialsAsync_LogsWhenCredentialFailsToLoad()
207+
{
208+
// Arrange
209+
var logger = new LoggerFactory().CreateLogger<DefaultCredentialsLoader>();
210+
var credentialLoader = new DefaultCredentialsLoader(logger);
211+
212+
var invalidCredential = new CredentialDescription
213+
{
214+
SourceType = CredentialSource.Path,
215+
ReferenceOrValue = "InvalidCredential"
216+
};
217+
var credentials = new List<CredentialDescription> { invalidCredential };
218+
219+
var credentialSourceLoaderMock = new Mock<ICredentialSourceLoader>();
220+
credentialSourceLoaderMock
221+
.Setup(loader => loader.LoadIfNeededAsync(
222+
It.Is<CredentialDescription>(c => c.ReferenceOrValue == "InvalidCredential"), null))
223+
.ThrowsAsync(new Exception("Loading failed"));
224+
225+
credentialLoader.CredentialSourceLoaders[CredentialSource.Path] = credentialSourceLoaderMock.Object;
226+
227+
// Act
228+
var result = await credentialLoader.LoadFirstValidCredentialsAsync(credentials);
229+
230+
// Assert
231+
Assert.Null(result);
232+
string expectedMessage = $"Failed to load credential: {invalidCredential}. Exception: Loading failed";
233+
//Assert.Contains(expectedMessage, logger.LoggedMessages[0], StringComparison.Ordinal);
234+
}
155235
}
156236
}

tests/Microsoft.Identity.Web.Test/Microsoft.Identity.Web.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2424
<PrivateAssets>all</PrivateAssets>
2525
</PackageReference>
26+
<PackageReference Include="Moq" Version="4.20.72" />
2627
<PackageReference Include="System.Text.Json" Version="$(SystemTextJsonVersion)" />
2728
<PackageReference Include="Microsoft.Identity.Abstractions" Version="$(MicrosoftIdentityAbstractionsVersion)" />
2829
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNetTestSdkVersion)" />

0 commit comments

Comments
 (0)