Search code examples
c#asp.net-coreidentityserver4

How to fix "Object reference not set to an instance of an object" - when calling RequestClientCredentialsTokenAsync?


When I'm trying to send a request to:

 var client = new HttpClient();
 var resp = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                Address = "http://localhost:5000/connect/token",
                ClientId = clientId.AsString(),
                ClientSecret = clientSecret,
                GrantType = grantType,
                Scope = scopes
            });

I'm catching an exception: System.NullReferenceException: 'Object reference not set to an instance of an object:

crit: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Unhandled exception: Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
   at IdentityServer4.Validation.DefaultClientConfigurationValidator.ValidateUriSchemesAsync(ClientConfigurationValidationContext context) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Validation\Default\DefaultClientConfigurationValidator.cs:line 148
   at IdentityServer4.Validation.DefaultClientConfigurationValidator.ValidateAsync(ClientConfigurationValidationContext context) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Validation\Default\DefaultClientConfigurationValidator.cs:line 52
   at IdentityServer4.Stores.ValidatingClientStore`1.FindClientByIdAsync(String clientId) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Stores\ValidatingClientStore.cs:line 61
   at IdentityServer4.Stores.IClientStoreExtensions.FindEnabledClientByIdAsync(IClientStore store, String clientId) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Extensions\IClientStoreExtensions.cs:line 23
   at IdentityServer4.Validation.ClientSecretValidator.ValidateAsync(HttpContext context) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Validation\Default\ClientSecretValidator.cs:line 67
   at IdentityServer4.Endpoints.TokenEndpoint.ProcessTokenRequestAsync(HttpContext context) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Endpoints\TokenEndpoint.cs:line 78
   at IdentityServer4.Endpoints.TokenEndpoint.ProcessAsync(HttpContext context) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Endpoints\TokenEndpoint.cs:line 70
   at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Hosting\IdentityServerMiddleware.cs:line 54

It's a really "good" describing about error... I'm trying to debug identity code from the library by using resharper. When I'm stepped the line 58 of ValidatingClientStore.cs file which represented by this code:

 var context = new ClientConfigurationValidationContext(client)

I'm getting the error I've mentioned above. It's just redirected me to

C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Validation\Default\DefaultClientConfigurationValidator.cs:line 148 

for the method signature... That's all. I can't understand what I'm doing wrong...I'm trying to override the identity components and I'm stuck with that error. My Startup.cs configuration:

 public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var scope = Configuration["Authentication:Scope:Name"];

            services.AddCors(options =>
            {
                // this defines a CORS policy called "default"
                options.AddPolicy("default", policy =>
                {
                    policy.WithOrigins("http://localhost:4300")
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                });
            });

            services.AddAuth(options =>
            {
                options.Security = new SecurityOptions
                {
                    RequiredScope = scope,
                    IntrospectionOptions = new OAuth2IntrospectionOptions
                    {
                        Authority = Configuration["Authentication:Settings:Authority"],
                        ClientId = Configuration["Authentication:Settings:ApiName"],
                        ClientSecret = Configuration["Authentication:Settings:ApiSecret"],
                        SaveToken = bool.Parse(Configuration["Authentication:Settings:SaveToken"]),
                        NameClaimType = Configuration["Authentication:Settings:NameClaimType"],
                        RoleClaimType = Configuration["Authentication:Settings:RoleClaimType"]
                    }
                };
            });

            services.Configure<List<ApiResourceOption>>(Configuration.GetSection("ApiResources"));
            services.Configure<List<ClientOption>>(Configuration.GetSection("Clients"));
            services.Configure<IdentityServerAuthenticationOptions>(Configuration.GetSection("Authentication:Settings"));

            //register main stores for identity
            services.AddIdentityCore<ApplicationUser>()
                .AddRoles<ApplicationRole>()
                .AddUserStore<ApplicationUserStore>()
                .AddRoleStore<ApplicationRoleStore>()
                .AddUserManager<ApplicationUserManager>()
                .AddUserValidator<CustomUserValidator<ApplicationUser>>()
                .AddDefaultTokenProviders();


            //register identity server 
            services.AddIdentityServer(c =>
                {
                    c.Caching.ClientStoreExpiration = TimeSpan.FromDays(1);
                    c.Caching.ResourceStoreExpiration = TimeSpan.FromDays(1);
                })
                .AddAspNetIdentity<ApplicationUser>()
                .AddClientStore<ApplicationClientStore>()
                .AddResourceStore<ApplicationResourceStore>()
                .AddProfileService<ProfileService<ApplicationUser>>()
                .AddResourceOwnerValidator<CustomResourceOwnerEmailValidator<ApplicationUser>>()
                .AddDeveloperSigningCredential();


            services.AddScoped<IPasswordHasher<ApplicationUser>, IdentityHasherService<ApplicationUser>>();
            services.AddScoped<IPersistedGrantStore, ApplicationPersistedGrantStore>();

            services.TryAddScoped<IPasswordValidator<ApplicationUser>, PasswordValidator<ApplicationUser>>();
            services.TryAddScoped<IPasswordHasher<ApplicationUser>, PasswordHasher<ApplicationUser>>();
            services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
            services.TryAddScoped<IRoleValidator<ApplicationRole>, RoleValidator<ApplicationRole>>();
            services.TryAddScoped<IdentityErrorDescriber>();
            services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<ApplicationUser>>();
            services.TryAddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole>>();
            services.TryAddScoped<UserManager<ApplicationUser>, UserManager<ApplicationUser>>();
            services.TryAddScoped<SignInManager<ApplicationUser>, SignInManager<ApplicationUser>>();
            services.TryAddScoped<RoleManager<ApplicationRole>, AspNetRoleManager<ApplicationRole>>();


            services.Configure<AuthSettings>(Configuration.GetSection("Authentication:Settings"));

            string connection = Configuration.GetConnectionString("Default");
            services.AddDbContext<IdentityContext>(options =>
                options.UseSqlServer(connection));

            services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

            services.AddMvcCore().AddJsonFormatters();

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseCors("default");
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }


            app.UseIdentityServer();
            app.UseMvc();
        }
    }

resp.Value has a html page with error description: exception


Solution

  • According to the stack trace above, the exception occurs in ValidateUriSchemesAsync() code, so most likely there is a null value in RedirectUris or PostLogoutRedirectUris in one of the client configurations object.