Search code examples
cryptographyidentityserver4

CryptographicException when deploying IdentityServer4 solution with AddDeveloperSigningCredential to IIS


I have a working Auth service built on IdentityServer3 and .NET Framework. I'm in the process of building a new version of it on IdentityServer4 and ASP.NET Core. In this early stage in development, I'm still using AddDeveloperSigningCredential. When I deploy it to my local development box (Windows 10) in a console window, it runs fine. When I deploy it to IIS Express on my local development box, it gets the following error on startup:

UnauthorizedAccessException: Access to the path 'C:\Program Files\IIS Express\tempkey.rsa' is denied.

I don't really care if it runs in IIS Express (since it runs fine in a console window), but I include this information in case it is relevant to my problem.

When I deploy the solution to a remote server running IIS (Windows Server 2008 R2, IIS 7.5) it fails on startup with this error:

Application startup exception: 

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Object was not found
   at System.Security.Cryptography.CngKeyLite.GenerateNewExportableKey(String algorithm, Int32 keySize)
   at System.Security.Cryptography.RSAImplementation.RSACng.GetDuplicatedKeyHandle()
   at System.Security.Cryptography.RSAImplementation.RSACng.ExportKeyBlob(Boolean includePrivateParameters)
   at System.Security.Cryptography.RSAImplementation.RSACng.ExportParameters(Boolean includePrivateParameters)
   at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderExtensionsCrypto.AddDeveloperSigningCredential(IIdentityServerBuilder builder, Boolean persistKey, String filename)
   at Orvis.Authorization.Service.Startup.ConfigureServices(IServiceCollection services) in C:\Workspaces\Orvis\orvis-microservices\orvis-authorization\Orvis.Authorization.Service\Startup.cs:line 20

Will IdentityServer4 and, in particular AddDeveloperSigningCredential, work on Windows Server 2008 R2 and IIS 7.5 or do I need a newer development server? Or, if the age of the O/S is not the problem, what else might be causing this error?


Solution

  • Well I got this working. At some point along the way the symptom changed and I'm not sure why, but I'll recount here what I know.

    I originally had the .AddDeveloperSigningCertficate call hard-coded in my startup code - like this:

    services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddTestUsers(Config.GetTestUsers());
    

    That produced the WindowsCryptographicException on startup as noted in the original post. Following some updated IdentityServer4 documentation, I changed that to:

                var builder = services.AddIdentityServer()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddTestUsers(Config.GetTestUsers());
    
            if (Environment.IsDevelopment())
            {
                builder.AddDeveloperSigningCredential();
            }
            else
            {
                throw new Exception("Need to configure key material"); 
            }
    

    Once I made sure my target server had the correct environment variable to define itself as a Development environment, I think that should have produced the same result. But instead it produced the access denied error that I'd seen earlier in my attempts to deploy locally to IIS Express.

    Given that error, I was able to grant the IIS ApplicationPoolIdentity identity write access to c:\windows\system32\inetsrv, which is where it was trying to write the tempkey.rsa developer credential file. This article provides a good overview of ApplicationPoolIdentity and details on how to grant permissions to that identity for your app pool. Granting permissions to that system directory required first taking ownership of the directory.

    With all of that done, my service is now running successfully with the developer signing credentials in IIS on my development server.