diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs b/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs index 7bcfb4d4ce..72d052195b 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs @@ -12,6 +12,10 @@ using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens.Json; +#if NET9_0_OR_GREATER +using System.Threading; +#endif + namespace Microsoft.IdentityModel.JsonWebTokens { /// @@ -21,8 +25,11 @@ namespace Microsoft.IdentityModel.JsonWebTokens internal class JsonClaimSet { internal const string ClassName = "Microsoft.IdentityModel.JsonWebTokens.JsonClaimSet"; - +#if NET9_0_OR_GREATER + internal Lock _claimsLock = new(); +#else internal object _claimsLock = new(); +#endif internal readonly Dictionary _jsonClaims; private List _claims; diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/PublicAPI/net9.0/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.JsonWebTokens/PublicAPI/net9.0/InternalAPI.Unshipped.txt index e69de29bb2..1efbcd41f8 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/PublicAPI/net9.0/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.JsonWebTokens/PublicAPI/net9.0/InternalAPI.Unshipped.txt @@ -0,0 +1 @@ +Microsoft.IdentityModel.JsonWebTokens.JsonClaimSet._claimsLock -> System.Threading.Lock \ No newline at end of file diff --git a/src/Microsoft.IdentityModel.Tokens/Encryption/SymmetricKeyWrapProvider.cs b/src/Microsoft.IdentityModel.Tokens/Encryption/SymmetricKeyWrapProvider.cs index ec8d878fe9..eda3521eab 100644 --- a/src/Microsoft.IdentityModel.Tokens/Encryption/SymmetricKeyWrapProvider.cs +++ b/src/Microsoft.IdentityModel.Tokens/Encryption/SymmetricKeyWrapProvider.cs @@ -5,6 +5,10 @@ using System.Security.Cryptography; using Microsoft.IdentityModel.Logging; +#if NET9_0_OR_GREATER +using System.Threading; +#endif + namespace Microsoft.IdentityModel.Tokens { /// @@ -15,9 +19,13 @@ public class SymmetricKeyWrapProvider : KeyWrapProvider private static readonly byte[] _defaultIV = new byte[] { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; private const int _blockSizeInBits = 64; private const int _blockSizeInBytes = _blockSizeInBits >> 3; - private static readonly object _encryptorLock = new object(); - private static readonly object _decryptorLock = new object(); - +#if NET9_0_OR_GREATER + private static readonly Lock s_encryptorLock = new(); + private static readonly Lock s_decryptorLock = new(); +#else + private static readonly object s_encryptorLock = new(); + private static readonly object s_decryptorLock = new(); +#endif private Lazy _symmetricAlgorithm; private ICryptoTransform _symmetricAlgorithmEncryptor; private ICryptoTransform _symmetricAlgorithmDecryptor; @@ -259,7 +267,7 @@ Return an error if (_symmetricAlgorithmDecryptor == null) { - lock (_decryptorLock) + lock (s_decryptorLock) { if (_symmetricAlgorithmDecryptor == null) _symmetricAlgorithmDecryptor = _symmetricAlgorithm.Value.CreateDecryptor(); @@ -409,7 +417,7 @@ private byte[] WrapKeyPrivate(byte[] inputBuffer, int inputOffset, int inputCoun if (_symmetricAlgorithmEncryptor == null) { - lock (_encryptorLock) + lock (s_encryptorLock) { if (_symmetricAlgorithmEncryptor == null) _symmetricAlgorithmEncryptor = _symmetricAlgorithm.Value.CreateEncryptor(); diff --git a/src/Microsoft.IdentityModel.Tokens/SecurityKey.cs b/src/Microsoft.IdentityModel.Tokens/SecurityKey.cs index 72cba31745..0e0dd8f648 100644 --- a/src/Microsoft.IdentityModel.Tokens/SecurityKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/SecurityKey.cs @@ -5,6 +5,10 @@ using System.Text.Json.Serialization; using Microsoft.IdentityModel.Logging; +#if NET9_0_OR_GREATER +using System.Threading; +#endif + namespace Microsoft.IdentityModel.Tokens { /// @@ -13,9 +17,13 @@ namespace Microsoft.IdentityModel.Tokens public abstract class SecurityKey { private CryptoProviderFactory _cryptoProviderFactory; - private object _internalIdLock = new object(); - private string _internalId; +#if NET9_0_OR_GREATER + private readonly Lock _internalIdLock = new(); +#else + private readonly object _internalIdLock = new(); +#endif + private string _internalId; internal SecurityKey(SecurityKey key) { _cryptoProviderFactory = key._cryptoProviderFactory; diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs index b77ef2b3c5..21a9b76cda 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/TokenValidationResult.cs @@ -30,7 +30,11 @@ public class TokenValidationResult // reordered relative to the other operations. The rest of the objects are not because the .NET memory model // guarantees object writes are store releases and that reads won't be introduced. private volatile bool _claimsIdentityInitialized; +#if NET9_0_OR_GREATER + private Lock _claimsIdentitySyncObj; +#else private object _claimsIdentitySyncObj; +#endif private ClaimsIdentity _claimsIdentity; private Dictionary _claims; private Dictionary _propertyBag; @@ -196,6 +200,23 @@ internal ClaimsIdentity ClaimsIdentityNoLocking } } +#if NET9_0_OR_GREATER + /// Gets the object to use in for double-checked locking. + private Lock ClaimsIdentitySyncObj + { + get + { + Lock syncObj = _claimsIdentitySyncObj; + if (syncObj is null) + { + Interlocked.CompareExchange(ref _claimsIdentitySyncObj, new Lock(), null); + syncObj = _claimsIdentitySyncObj; + } + + return syncObj; + } + } +#else /// Gets the object to use in for double-checked locking. private object ClaimsIdentitySyncObj { @@ -211,7 +232,7 @@ private object ClaimsIdentitySyncObj return syncObj; } } - +#endif /// /// Gets or sets the that occurred during validation. /// diff --git a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidatedToken.cs b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidatedToken.cs index f2e87c33ef..149d5213ea 100644 --- a/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidatedToken.cs +++ b/src/Microsoft.IdentityModel.Tokens/Validation/Results/ValidatedToken.cs @@ -114,9 +114,13 @@ ActorValidationResult is not null // reordered relative to the other operations. The rest of the objects are not because the .NET memory model // guarantees object writes are store releases and that reads won't be introduced. private volatile bool _claimsIdentityInitialized; - private object? _claimsIdentitySyncObj; private ClaimsIdentity? _claimsIdentity; private Dictionary? _claims; +#if NET9_0_OR_GREATER + private Lock? _claimsIdentitySyncObj; +#else + private object? _claimsIdentitySyncObj; +#endif /// /// The created from the validated security token. @@ -190,6 +194,23 @@ internal ClaimsIdentity ClaimsIdentityNoLocking } } +#if NET9_0_OR_GREATER + /// Gets the Lock to use in for double-checked locking. + private Lock ClaimsIdentitySyncObj + { + get + { + Lock? syncObj = _claimsIdentitySyncObj; + if (syncObj is null) + { + Interlocked.CompareExchange(ref _claimsIdentitySyncObj, new Lock(), null); + syncObj = _claimsIdentitySyncObj; + } + + return syncObj; + } + } +#else /// Gets the object to use in for double-checked locking. private object ClaimsIdentitySyncObj { @@ -205,6 +226,7 @@ private object ClaimsIdentitySyncObj return syncObj; } } +#endif #endregion #region Logging diff --git a/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs b/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs index 39ecb14492..1c373468a9 100644 --- a/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs @@ -5,6 +5,9 @@ using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using Microsoft.IdentityModel.Logging; +#if NET9_0_OR_GREATER +using System.Threading; +#endif namespace Microsoft.IdentityModel.Tokens { @@ -16,8 +19,11 @@ public class X509SecurityKey : AsymmetricSecurityKey AsymmetricAlgorithm _privateKey; bool _privateKeyAvailabilityDetermined; AsymmetricAlgorithm _publicKey; - object _thisLock = new Object(); - +#if NET9_0_OR_GREATER + Lock _thisLock = new(); +#else + object _thisLock = new(); +#endif internal X509SecurityKey(JsonWebKey webKey) : base(webKey) { @@ -110,12 +116,14 @@ public AsymmetricAlgorithm PublicKey return _publicKey; } } - +#if NET9_0_OR_GREATER + Lock ThisLock => _thisLock; +#else object ThisLock { get { return _thisLock; } } - +#endif /// /// Gets a bool indicating if a private key exists. /// diff --git a/src/Microsoft.IdentityModel.Xml/EnvelopedSignatureWriter.cs b/src/Microsoft.IdentityModel.Xml/EnvelopedSignatureWriter.cs index 88fd9267c9..de2ad9fa7b 100644 --- a/src/Microsoft.IdentityModel.Xml/EnvelopedSignatureWriter.cs +++ b/src/Microsoft.IdentityModel.Xml/EnvelopedSignatureWriter.cs @@ -8,6 +8,10 @@ using Microsoft.IdentityModel.Tokens; using static Microsoft.IdentityModel.Logging.LogHelper; +#if NET9_0_OR_GREATER +using System.Threading; +#endif + namespace Microsoft.IdentityModel.Xml { /// @@ -39,7 +43,12 @@ public class EnvelopedSignatureWriter : DelegatingXmlDictionaryWriter private bool _signaturePlaceholderWritten; private SigningCredentials _signingCredentials; private MemoryStream _internalStream; - private object _signatureLock = new object(); + +#if NET9_0_OR_GREATER + private Lock _signatureLock = new(); +#else + private object _signatureLock = new(); +#endif /// /// Initializes an instance of . The returned writer can be directly used diff --git a/test/Microsoft.IdentityModel.Abstractions.Tests/Properties/AssemblyInfo.cs b/test/Microsoft.IdentityModel.Abstractions.Tests/Properties/AssemblyInfo.cs index 5f8b323cff..ad80aa4c70 100644 --- a/test/Microsoft.IdentityModel.Abstractions.Tests/Properties/AssemblyInfo.cs +++ b/test/Microsoft.IdentityModel.Abstractions.Tests/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright(c) Microsoft Corporation.All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System;