[Bug] ArgumentNullException / "A device attached to the system is not functioning" in RSACryptoServiceProvider under heavy load
See original GitHub issueWhich Version of MSAL are you using ? Microsoft.Identity.Client 4.22.0
Platform net461
What authentication flow has the issue?
- Desktop / Mobile
- Interactive
- Integrated Windows Auth
- Username Password
- Device code flow (browserless)
- Web App
- Authorization code
- OBO
- Web API
- OBO
Is this a new or existing app?
The app was in production with the library Microsoft.IdentityModel.Clients.ActiveDirectory 5.2.8
. I haven’t upgraded MSAL, but sometimes started to observe an exception: The parameter is incorrect. Exception type: CryptographicException
. I’ve updated to Microsoft.Identity.Client 4.22.0
but still continue receiving exceptions with the similar stack trace: Value cannot be null. Parameter name: keyBlob Exception type: ArgumentNullException
.
Repro
It’s hard to reproduce, issue began to appear when request rate was increased. It usually happens after swap production & staging slots during deployment in Azure Cloud service (Classic)
or after scaling out. Restarting problem VM fixes the problem.
This code initializes KeyVaultClient(AuthenticationCallback authenticationCallback, params DelegatingHandler[] handlers)
in AuthenticationCallback
delegate:
private async Task<string> GetToken(string authority, string resource, string scope)
{
IConfidentialClientApplication clientApplication = ConfidentialClientApplicationBuilder
.Create(this.clientId)
.WithAuthority(new Uri(authority), validateAuthority: true)
.WithCertificate(this.clientCertificate)
.Build();
AuthenticationResult result = await clientApplication
.AcquireTokenForClient(new[] { scope }) // exception throws here
.ExecuteAsync()
.ConfigureAwait(false);
return result.AccessToken;
}
Expected behavior Acquire authentication token without an exception.
Actual behavior Sometimes exception is being thrown:
Value cannot be null.
Parameter name: keyBlob Exception type: ArgumentNullException
Stack trace:
at System.Security.Cryptography.RSACryptoServiceProvider.IsPublic(Byte[] keyBlob)
at System.Security.Cryptography.X509Certificates.PublicKey.get_Key()
at Microsoft.Identity.Client.Platforms.net45.NetDesktopCryptographyManager.SignWithCertificate(String message, X509Certificate2 certificate)
at Microsoft.Identity.Client.Internal.JsonWebToken.Sign(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialHelper.CreateClientCredentialBodyParameters(ICoreLogger logger, ICryptographyManager cryptographyManager, ClientCredentialWrapper clientCredential, String clientId, AuthorityEndpoints endpoints, Boolean sendX5C)
at Microsoft.Identity.Client.OAuth2.TokenClient.AddBodyParamsAndHeaders(IDictionary`2 additionalBodyParameters, String scopes)
at Microsoft.Identity.Client.OAuth2.TokenClient.<SendTokenRequestAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<SendTokenRequestAsync>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<FetchNewAccessTokenAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.<ExecuteAsync>d__3.MoveNext()
Possible Solution None.
Additional context/ Logs / Screenshots
Stack trace of the exception in Microsoft.IdentityModel.Clients.ActiveDirectory 5.2.8
was:
The parameter is incorrect.
Exception type: CryptographicException
Stack trace:
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature)
at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Platform.SigningHelper.SignWithCertificate(String message, X509Certificate2 certificate)
at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.ClientCreds.JsonWebToken.Sign(IClientAssertionCertificate credential, Boolean sendX5c)
at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.ClientCreds.ClientKey.AddToParameters(IDictionary`2 parameters)
at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.<SendTokenRequestAsync>d__70.MoveNext()
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (2 by maintainers)
Top GitHub Comments
Thanks for the updates. Btw workaround with self-signing helped. Waiting for your PR be merged.
Current progress: https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/2276