0

I'm encountering an InvalidOperationException in my ASP.NET Core application when integrating with IdentityServer4. In local everything works fine but when I replace my old projects (Client + Auth) I get this error message and many more but this one was the first one I saw in Event Viewer. The error message is:

System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.
The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
   at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
   at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.<>c__DisplayClass0_0.<<HandleAsync>g__Handle|0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|8_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)

Environment

Client Application: ASP.NET Core 7
IdentityServer: ASP.NET Core 8
Hosting: IIS

Client Application Configuration

Here is my Program.cs file for the client application:

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

// Configure authentication
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
    options.LoginPath = "/account/login";
    options.LogoutPath = "/account/logout";
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.Authority = builder.Configuration["Auth"];
    options.ClientId = "MyAPP";
    options.ClientSecret = "secret3";
    options.ResponseType = "code";
    options.RequireHttpsMetadata = true;
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/signin-oidc");

    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.SaveTokens = true;
    options.UseTokenLifetime = true;
    options.GetClaimsFromUserInfoEndpoint = true;

    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        NameClaimType = "name",
        RoleClaimType = "role",
    };

    options.Events = new OpenIdConnectEvents
    {
        OnTicketReceived = context =>
        {
            context.Properties.IsPersistent = true;
            context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddDays(90);
            return Task.CompletedTask;
        },
        OnRemoteFailure = context =>
        {
            context.Response.Redirect("/");
            context.HandleResponse(); // Prevents default exception
            return Task.CompletedTask;
        },
        OnAuthorizationCodeReceived = context =>
        {
            return Task.CompletedTask;
        }
    };
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

IdentityServer Configuration

Here is my Startup.cs file for the IdentityServer:

using IdentityServer.Quickstart.Account;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using IdentityServerHost.Quickstart.UI;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

namespace IdentityServer
{
    public class Startup
    {
        public IWebHostEnvironment Environment { get; }

        public Startup(IWebHostEnvironment environment)
        {
            Environment = environment;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSession();
            services.AddCors(options =>
            {
                options.AddPolicy(name: "AuthCorsPolicy",
                                  builder =>
                                  {
                                      builder.WithOrigins("http://localhost:5001",
                                                          "http://localhost:44314",
                                                          "http://localhost:44396")
                                                            .AllowAnyHeader()
                                                            .AllowCredentials()
                                                            .AllowAnyMethod();
                                  });
            });

            services.AddSingleton<ICorsPolicyService>((container) =>
            {
                var logger = container.GetRequiredService<ILogger<DefaultCorsPolicyService>>();
                return new DefaultCorsPolicyService(logger)
                {
                    AllowedOrigins = { "http://localhost:5001", "http://localhost:44314", "http://localhost:44396" },
                };
            });

            services.AddControllersWithViews();

            services.AddScoped(_ => new HorizonUsersFetcher());

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie();

            services.AddAuthorization();

            var builder = services.AddIdentityServer().AddCorsPolicyService<DefaultCorsPolicyService>();

            // Configurations for different environments
            builder.AddInMemoryIdentityResources(Config.IdentityResources);
            builder.AddInMemoryApiScopes(Config.ApiScopes);
            builder.AddInMemoryApiResources(Config.ApiResources);
            builder.AddInMemoryClients(Config.Clients);

            builder.Services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
            builder.Services.AddTransient<IProfileService, ProfileService>();

            if (Environment.IsDevelopment())
            {
                builder.AddDeveloperSigningCredential();
            }
            else
            {
                string certName = XDocument.Parse(File.ReadAllText("Web.config")).Descendants("add").Where(x => x.Attribute("key").Value == "CertificateName").Select(x => x.Attribute("value")).FirstOrDefault().Value;
                builder.AddSigningCredential("CN=" + certName);
            }
        }

        public void Configure(ILoggerFactory _loggerFactory, IApplicationBuilder app)
        {
            if (Environment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseSession();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseCors("AuthCorsPolicy");
            app.UseIdentityServer();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
            });
        }
    }
}

Troubleshooting Steps Taken

Verified Configuration:
    Confirmed that the DefaultScheme and DefaultChallengeScheme are set correctly in both client and server.
    Ensured AuthenticateurURL in appsettings.json points to the correct IdentityServer URL.

Logging:
    Implemented Serilog in both client and server applications for detailed logging.
    Reviewed logs but did not find additional information on the cause of the issue.

IIS Logs:
    Checked IIS logs for any additional details but found nothing conclusive.

Questions

Middleware Order:
    Could there be an issue with the order of middleware in Startup.cs?
    Is there a specific order that UseAuthentication and UseAuthorization should follow?

Configuration Issues:
    Are there any common misconfigurations that could lead to this issue?
    How can I further debug this problem to identify the root cause?

Logging and Diagnostics:
    What additional logging or diagnostics can I enable to get more insights into this issue?

Any insights or suggestions on how to resolve this issue would be greatly appreciated. Thank you!

1
  • Since your problem cannot be reproduced, here are some suggetions. The order of middleware especially authentication and authorization looks correct and it is often not the issue. The error message is specific and you need to ensure the schemes of client application match IdentityServer asks for. And try modify the .net core version. IdentityServer has logging tools too, try get more information. Commented Jun 6 at 6:33

0