简体   繁体   中英

InvalidOperationException: Key type not specified. Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ConfigureSigningCredentials.LoadKey()

Summary

Attempting to publish a basic .NET Core React app with auth functionality I am receiving an error with IdentityServer. This is using dotnet new react --auth Individual, .Net Core 3.0 Preview5, and following the instructions here and here .

I've uploaded the PFX via the TLS/SSL settings. I've also ensured the certificate works on my dev environment, finding that GetMyX509Certificate returns the cert.

The code causing the issue seems to be in Configure in Startup.cs when running app.UseIdentityServer():

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //...

        Log.Information("Configure - running app.Use: Authentication, IdentityServer");

       Log.Information("Configure - running app.Use: Authentication");
        app.UseAuthentication();
        Log.Information("Configure - running app.Use: IdentityServer");
        app.UseIdentityServer();

        //CODE DOESN'T MAKE IT HERE!!!
        Log.Information("Configure - running app.UseMvc");

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
        });

        Log.Information("Configure - running app.UseSpa");

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseReactDevelopmentServer(npmScript: "start");
            }
        });

        Log.Information("Configure - Done!");
    }

The Error

Activating ASPNETCORE_DETAILEDERRORS = true , I am getting the following error:

InvalidOperationException: Key type not specified

Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ConfigureSigningCredentials.LoadKey()
    Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ConfigureSigningCredentials.Configure(ApiAuthorizationOptions options)
    Microsoft.Extensions.Options.OptionsFactory<TOptions>.Create(string name)
    Microsoft.Extensions.Options.OptionsManager<TOptions>+<>c__DisplayClass5_0.<Get>b__0()
    System.Lazy<T>.ViaFactory(LazyThreadSafetyMode mode)
    System.Lazy<T>.ExecutionAndPublication(LazyHelper executionAndPublication, bool useDefaultConstructor)
    System.Lazy<T>.CreateValue()
    System.Lazy<T>.get_Value()
    Microsoft.Extensions.Options.OptionsCache<TOptions>.GetOrAdd(string name, Func<TOptions> createOptions)
    Microsoft.Extensions.Options.OptionsManager<TOptions>.Get(string name)
    Microsoft.Extensions.Options.OptionsManager<TOptions>.get_Value()
    Microsoft.Extensions.DependencyInjection.IdentityServerBuilderConfigurationExtensions+<>c.<AddClients>b__7_1(IServiceProvider sp)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine+<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
    Microsoft.AspNetCore.Builder.IdentityServerApplicationBuilderExtensions.TestService(IServiceProvider serviceProvider, Type service, ILogger logger, string message, bool doThrow)
    Microsoft.AspNetCore.Builder.IdentityServerApplicationBuilderExtensions.Validate(IApplicationBuilder app)
    Microsoft.AspNetCore.Builder.IdentityServerApplicationBuilderExtensions.UseIdentityServer(IApplicationBuilder app)
    ReactWithAuth.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env) in Startup.cs
    System.RuntimeMethodHandle.InvokeMethod(object target, object[] arguments, Signature sig, bool constructor, bool wrapExceptions)
    System.Reflection.RuntimeMethodInfo.Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
    Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder.Invoke(object instance, IApplicationBuilder builder)
    Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder+<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
    Microsoft.AspNetCore.Hosting.Internal.ConventionBasedStartup.Configure(IApplicationBuilder app)
    Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter+<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder)
    Microsoft.AspNetCore.Server.IIS.Core.IISServerSetupFilter+<>c__DisplayClass2_0.<Configure>b__0(IApplicationBuilder app)
    Microsoft.AspNetCore.HostFilteringStartupFilter+<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
    Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
        Microsoft.Extensions.DependencyInjection.IdentityServerBuilderExtensionsCrypto.AddSigningCredential(IIdentityServerBuilder builder, X509Certificate2 certificate)
        Projects.Startup.ConfigureServices(IServiceCollection services) in Startup.cs
        System.RuntimeMethodHandle.InvokeMethod(object target, object[] arguments, Signature sig, bool constructor, bool wrapExceptions)
        System.Reflection.RuntimeMethodInfo.Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
        Microsoft.AspNetCore.Hosting.Internal.ConfigureServicesBuilder.InvokeCore(object instance, IServiceCollection services)
        Microsoft.AspNetCore.Hosting.Internal.ConfigureServicesBuilder+<>c__DisplayClass9_0.<Invoke>g__Startup|0(IServiceCollection serviceCollection)
        Microsoft.AspNetCore.Hosting.Internal.StartupLoader+ConfigureServicesDelegateBuilder<TContainerBuilder>+<>c__DisplayClass15_0.<BuildStartupServicesFilterPipeline>g__RunPipeline|0(IServiceCollection services)
        Microsoft.AspNetCore.Hosting.Internal.ConfigureServicesBuilder.Invoke(object instance, IServiceCollection services)
        Microsoft.AspNetCore.Hosting.Internal.ConfigureServicesBuilder+<>c__DisplayClass8_0.<Build>b__0(IServiceCollection services)
        Microsoft.AspNetCore.Hosting.Internal.StartupLoader+ConfigureServicesDelegateBuilder<TContainerBuilder>+<>c__DisplayClass14_0.<ConfigureServices>g__ConfigureServicesWithContainerConfiguration|0(IServiceCollection services)
        Microsoft.AspNetCore.Hosting.Internal.ConventionBasedStartup.ConfigureServices(IServiceCollection services)
        Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices()
        Microsoft.AspNetCore.Hosting.Internal.WebHost.Initialize()
        Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

Things I've tried

There's not much out there in the way of solutions. The IdentityServer4 only talks about types in terms ofGrant Types , but this seems prior to that.

As you already answered - The solution is to add the following settings into appsettings.json, within the "IdentityServer" brackets. This followed the "Clients" element:

For File

 "IdentityServer": {
    "Key": {
      "Type": "File",
      "FilePath": "C:\cert.pfx",
      "Password": "password123"
    }
  }

For Development (don't use in production obviously)

 "IdentityServer": {
    "Key": {
      "Type": "Development"
    }
  }

For Store

"IdentityServer": {
  "Key": {
    "Type": "Store",
    "StoreName": "My",
    "StoreLocation": "CurrentUser",
    "Name": "CN=MyApplication"
  }
}

link

The solution is to add the following settings into appsettings.json, within the "IdentityServer" brackets. This followed the "Clients" element:

  "IdentityServer": { 
    "Key": {
      "Type": "Store",
      "StoreName": "My",
      "StoreLocation": "CurrentUser",
      "Name": "CN=**WHATEVER NAME YOU USED AS THE DISTINGUISHED SUBJECT FOR YOUR CERT**"
    }

This follows the instructions here . Note, that this was accomplished with a self-signed certificate created with OpenSSL following this post.

From the above mentioned code , i am assuming that below line of coding is causing nullargument exception.

.AddSigningCredential(cert);

because the **cert** is null,which comes down to your method GetMyX509Certificate

try
        {
            System.Diagnostics.Trace.TraceInformation($"HELLO! TRYING TO GET THE CERTIFICATE");
            return new X509Certificate2(File.ReadAllBytes(pfxFilePath), password, sFlags);
        }
        catch (PlatformNotSupportedException ex)
        {
            System.Diagnostics.Trace.TraceError($"HELLO! {ex.Message}");
            if(sFlags.HasFlag(X509KeyStorageFlags.EphemeralKeySet))
            {
                return GetMyX509Certificate(pfxFilePath,password,X509KeyStorageFlags.MachineKeySet);
            } else 
            {
                return null;
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Trace.TraceError($"HELLO! {ex.Message}");
            return null;
        }

Since you code is not throwing **PlatformNotSupportedException** type of exception, for sure it will throwing Generic Exception which will be later catched by your last line

 catch (Exception ex)
        {
            System.Diagnostics.Trace.TraceError($"HELLO! {ex.Message}");
            return null;
        }

and from here you are returning null which internally giving you the actual error.

I don't understand why are you not able to use KUDU, but if i were you , i would suggest you to enable information logging using some logging library , eg File system logging or Application insighy using custom telemetry.

Hope it helps.

{
  "ConnectionStrings": {
    "DefaultConnection": ""
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "IdentityServer": {
    "Clients": {
      "Project01": {
        "Profile": "IdentityServerSPA"
      }
    },
    "Key": {
      "Type": "Development"
    }
  },
  "AllowedHosts": "*"
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM