Skip to content

Commit 8507505

Browse files
cpp11nullptrZhenya Polyvanyi
andauthored
Fix initialization of ConfidentialClientApplicationOptions in MergedOptions (#3760)
Co-authored-by: Zhenya Polyvanyi <iepoly@microsoft.com>
1 parent fb710b8 commit 8507505

2 files changed

Lines changed: 41 additions & 3 deletions

File tree

src/Microsoft.Identity.Web.TokenAcquisition/MergedOptions.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using System.Threading;
78
using IdWebLogger = Microsoft.Extensions.Logging;
89
using Microsoft.Identity.Abstractions;
910

@@ -32,10 +33,11 @@ public ConfidentialClientApplicationOptions ConfidentialClientApplicationOptions
3233
{
3334
get
3435
{
35-
if (_confidentialClientApplicationOptions == null)
36+
if (_confidentialClientApplicationOptions is null)
3637
{
37-
_confidentialClientApplicationOptions = new ConfidentialClientApplicationOptions();
38-
UpdateConfidentialClientApplicationOptionsFromMergedOptions(this, _confidentialClientApplicationOptions);
38+
var options = new ConfidentialClientApplicationOptions();
39+
UpdateConfidentialClientApplicationOptionsFromMergedOptions(this, options);
40+
Interlocked.CompareExchange(ref _confidentialClientApplicationOptions, options, null);
3941
}
4042

4143
return _confidentialClientApplicationOptions;

tests/Microsoft.Identity.Web.Test/MergedOptionsTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
using System.Collections.Generic;
55
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using Microsoft.Identity.Abstractions;
79
using Xunit;
810

@@ -313,5 +315,39 @@ public void PrepareAuthorityInstanceForMsal_LeavesNullPreparedInstance_WhenNoCon
313315
Assert.Null(options.Authority);
314316
Assert.Null(options.PreparedInstance);
315317
}
318+
319+
[Fact]
320+
public async Task ConfidentialClientApplicationOptions_IsThreadSafe()
321+
{
322+
// Arrange
323+
var mergedOptions = new MergedOptions
324+
{
325+
ClientId = "test-client-id",
326+
ClientSecret = "test-client-secret",
327+
Instance = "https://login.microsoftonline.com/",
328+
TenantId = "test-tenant-id",
329+
};
330+
331+
const int threadCount = 50;
332+
var barrier = new Barrier(threadCount);
333+
var results = new Microsoft.Identity.Client.ConfidentialClientApplicationOptions[threadCount];
334+
335+
// Act
336+
var tasks = Enumerable.Range(0, threadCount).Select(i => Task.Run(() =>
337+
{
338+
barrier.SignalAndWait();
339+
results[i] = mergedOptions.ConfidentialClientApplicationOptions;
340+
})).ToArray();
341+
await Task.WhenAll(tasks);
342+
343+
// Assert
344+
for (int i = 0; i < threadCount; i++)
345+
{
346+
Assert.NotNull(results[i]);
347+
Assert.Equal("test-client-id", results[i].ClientId);
348+
Assert.Equal("test-client-secret", results[i].ClientSecret);
349+
Assert.Equal("test-tenant-id", results[i].TenantId);
350+
}
351+
}
316352
}
317353
}

0 commit comments

Comments
 (0)