CryptographicException while calling /.well-known/openid-configuration (.NET 8)
Tobias-08 opened this issue ยท 14 comments
Which version of Duende IdentityServer are you using?
7.0.1
Which version of .NET are you using?
.NET 8
Describe the bug
Calling /.well-known/openid-configuration
leads to CryptographicException: The system cannot find the file specified
since we migrated from .NET 6/IdentityServer 6.x to .NET 8/IdentityServer 7.x.
To Reproduce
- Setup an IdentityServer project in .NET 8 and serve it via IIS with
Load user profile: false
. - Call
/.well-known/openid-configuration
.
Expected behavior
It should work in .NET 8 even if Load user profile
is set to false
.
Log output/exception with stacktrace
CryptographicException: The system cannot find the file specified.
System.Security.Cryptography.X509Certificates.CertificatePal.FilterPFXStore(ReadOnlySpan<byte> rawData, SafePasswordHandle password, PfxCertStoreFlags pfxCertStoreFlags)
System.Security.Cryptography.X509Certificates.CertificatePal.FromBlobOrFile(ReadOnlySpan<byte> rawData, string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
System.Security.Cryptography.X509Certificates.X509Certificate..ctor(ReadOnlySpan<byte> data)
System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(byte[] rawData)
Duende.IdentityServer.Services.KeyManagement.X509KeyContainer.ToSecurityKey() in X509KeyContainer.cs
Duende.IdentityServer.Services.KeyManagement.AutomaticKeyManagerKeyStore+<>c.<GetValidationKeysAsync>b__5_0(KeyContainer x) in AutomaticKeyManagerKeyStore.cs
System.Linq.Enumerable+SelectArrayIterator<TSource, TResult>.Fill(ReadOnlySpan<TSource> source, Span<TResult> destination, Func<TSource, TResult> func)
System.Linq.Enumerable+SelectArrayIterator<TSource, TResult>.ToArray()
Duende.IdentityServer.Services.KeyManagement.AutomaticKeyManagerKeyStore.GetValidationKeysAsync() in AutomaticKeyManagerKeyStore.cs
Duende.IdentityServer.Services.DefaultKeyMaterialService.GetValidationKeysAsync() in DefaultKeyMaterialService.cs
Duende.IdentityServer.ResponseHandling.DiscoveryResponseGenerator.CreateDiscoveryDocumentAsync(string baseUrl, string issuerUri) in DiscoveryResponseGenerator.cs
Duende.IdentityServer.Endpoints.DiscoveryEndpoint.ProcessAsync(HttpContext context) in DiscoveryEndpoint.cs
Duende.IdentityServer.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IdentityServerOptions options, IEndpointRouter router, IUserSession userSession, IEventService events, IIssuerNameService issuerNameService, ISessionCoordinationService sessionCoordinationService) in IdentityServerMiddleware.cs
Duende.IdentityServer.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IdentityServerOptions options, IEndpointRouter router, IUserSession userSession, IEventService events, IIssuerNameService issuerNameService, ISessionCoordinationService sessionCoordinationService) in IdentityServerMiddleware.cs
Duende.IdentityServer.Hosting.MutualTlsEndpointMiddleware.Invoke(HttpContext context, IAuthenticationSchemeProvider schemes) in MutualTlsEndpointMiddleware.cs
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Duende.IdentityServer.Hosting.DynamicProviders.DynamicSchemeAuthenticationMiddleware.Invoke(HttpContext context) in DynamicSchemeAuthenticationMiddleware.cs
Duende.IdentityServer.Hosting.BaseUrlMiddleware.Invoke(HttpContext context) in BaseUrlMiddleware.cs
Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
Additional context
Background:
- We are running IdentityServer in IIS with an application pool configured with
Load user profile: false
. - This worked in .NET 6 but does not work in .NET 8.
- It works in .NET 8 if we set
Load user profile
totrue
.
Theory:
- The behaviour of
X509Certificate2
-constructor might have changed from .NET 6 to .NET 8 so that the workaround (type check) in IdentityServer'sX509KeyContainer
-implementation for theLoad user profile: false
-case might not work anymore.
Thanks for the detailed info @Tobias-08. A couple of questions:
- Are you using automatic key management with the UseX509Certificate enabled, or are you supplying an x509 cert as a manual signing key?
- Do you need to avoid loading the user profile/is this preventing you from upgrading while we investigate?
@josephdecock Thanks for your response. Regarding your questions:
- We are using automatic key management with
UseX509Certificate
enabled (because we are using RSK's WS-Federation plugin which requires this). - We are not in production yet so we are not blocked for the moment.
This has been asked about before in another support channel. I think that you are right @Tobias-08 that there is a change in behaviour of the constructor. It looks like the exception type thrown has changed in .NET 8 so we might need to update our code to detect the new exception type.
It looks like this is due to a changed behaviour from .NET 7 and up: dotnet/runtime@43c4405
Moving to IdentityServer repo to fix it.
@brockallen @josephdecock The exception type was changed in .NET 7. So technically we should patch IdSrv 6.x. But end of life for .NET 7 is less than two months away. I think a fix for IdSrv 7.x is enough. What do you think?
@Tobias-08 Do you think you could help me to get a value out of the exception thrown? I would need the value of CryptographicException.HResult
. I assume that it should be 0x80070002
(= -2147024894
), but I would like to verify before creating the patch.
@AndersAbel: Yes, you are right. CryptographicException.HResult
is -2147024894
.
@Tobias-08 Thank you!
@Tobias-08 If we merge this and put out a preview on Nuget, would you be able to help us test it?
@brockallen Could we merge this and put out another preview on 7.0.2 to get it tested in a proper environment? It's obviously not testable on a local development setup because the user profile is always available then.
@AndersAbel Yes, of course.
We're working on putting out a 7.0.3-preview.1 to test.
We've pushed a 7.0.3-preview.1 to NuGet with the proposed fix. Please have a look and let us know how it works. Thanks.
@brockallen @AndersAbel 7.0.3-preview.1
works as expected in my setup, i. e. it works with .NET 8 and Load user profile: false
.
Thanks!
7.0.3 Has been pushed to NuGet. Thanks!