I've found many threads about this issue, but not matter what I change it just doesn't work. I am desperate as I don't understand what is wrong.
My application works fine if run on IIS Express.
As soon as I deploy it to the IIS, it starts to complain about the "query string is too long"
What I don't understand is why it is calling Account\Login - my application has no controllers or any views. It is ASP.NET Core React template where we don't use controllers but our communication is fully through SignalR. We don't have even API controllers.
I tried to set web.config as is suggested on many places (for example here but it's suggested in many other threads) - it doesn't help.
I have identified that the issue in the code is setup of authorization in Program.cs/Startup .cs file. However, it is done according to Microsoft guide.
In my Program.cs I have this to configure authentication:
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
builder.Services.AddAuthorization(options => options.FallbackPolicy = options.DefaultPolicy);
If I run application via the IIS Express, it loads fine, authenticates user and everything seems to be working just fine. As soon as I deploy it to the IIS server, I receive this error:
Note: I have noticed that even if run on IIS Express, it still sends requests to /Account/Login but it doesn't crash the app for some reason.
What I really don't understand is, why is it calling Account/Login path, it just doesn't exist and I don't have it set anywhere in the code. And as mentioned, my application have no controllers or views. It's react application communicating with server via SignalR (but it doesn't get that far, so SignalR is not involved yet).
If I change the code above to:
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
builder.Services.AddAuthorization(options => options.FallbackPolicy = null);
then it won't crash, but it won't log in windows user either.
I tried many things in last two days but can't figure out, what is wrong.
I appreciate any ideas of what could be wrong.
Edit 1 - web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<security>
<requestFiltering removeServerHeader="true">
<requestLimits maxUrl="4096" maxQueryString="5000"></requestLimits>
</requestFiltering>
</security>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
<add name="X-Frame-Options" value="DENY" />
</customHeaders>
</httpProtocol>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="bin\x86\Debug\net6.0-windows\PPSim.Web.exe" arguments="" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" startupTimeLimit="3600" requestTimeout="23:00:00" hostingModel="inprocess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_HTTPS_PORT" value="443" />
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
</environmentVariables>
</aspNetCore>
</system.webServer>
<system.web>
<httpRuntime enableVersionHeader="false" maxQueryStringLength="32768" maxUrlLength="65536" />
</system.web>
</configuration>
Edit 2 - Program.cs:
var builder = WebApplication.CreateBuilder(args);
#region Services
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
builder.Services.AddAuthorization(options => options.FallbackPolicy = options.DefaultPolicy);
builder.Services.AddAntiforgery(options =>
{
options.HeaderName = CsrfConstants.CsrfHeaderName;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict;
});
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var settings = new JsonSerializerSettings { ContractResolver = new SignalRContractResolver() };
var serializer = JsonSerializer.Create(settings);
builder.Services.AddSingleton(serializer);
builder.Services.AddHsts(options =>
{
options.Preload = true;
options.IncludeSubDomains = true;
options.MaxAge = TimeSpan.FromDays(60);
});
builder.Services.AddSingleton<IUserSettingsWrapper, UserSettingsWrapper>();
builder.Services.AddSingleton<ISignalREventsPusher, SignalRDataPusher>();
builder.Services.AddSignalR().AddNewtonsoftJsonProtocol(options =>
{
options.PayloadSerializerSettings.ContractResolver = new CustomCamelCasePropertyNamesContractResolver();
options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.PayloadSerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
});
builder.Services.AddSingleton<IUserIdProvider, NameUserIdProvider>();
builder.Services.AddLogging(loggingBuilder =>
{ loggingBuilder.AddConfiguration(builder.Configuration.GetSection("Logging"));
loggingBuilder.AddConsole();
loggingBuilder.AddDebug();
});
builder.Services.AddCors(options =>
{
options.AddPolicy("CORSPermission", policy =>
{
policy.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed(host => true)
.AllowCredentials();
});
});
#endregion
var app = builder.Build();
#region Configure
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
app.Use((context, next) =>
{
var requestPath = context.Request.Path.Value;
if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
{
var tokenSet = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append(CsrfConstants.CsrfCookiesName, tokenSet.RequestToken!,
new CookieOptions
{
HttpOnly = false,
Secure = true, // 15018: Cookie generated by application does not contain the “Secure flag” attribute
SameSite = SameSiteMode.Strict
});
}
return next(context);
});
if (!app.Environment.IsDevelopment())
{
}
else
{
app.UseHsts();
//app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CORSPermission")
app.UseAuthentication();
app.UseAuthorization();
app.UseFileServer();
#endregion
app.MapFallbackToFile("index.html");
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<SimulatorHub>("/SimulatorHub",
options => options.Transports = GetTransportToUse(app.Environment)).RequireCors("CORSPermission");
});
app.Run();