I am implementing simple signal R real-time messaging. It works absolutely fine in local but moment its deployed i get CORS error
8DUpdate.html:1 Access to fetch at 'https://test.test.test.com/chatHub/negotiate?negotiateVersion=1' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.Understand this errorAI signalr.min.js:1
Preflight request :
Request URL: https://test.test.test.com/chatHub/negotiate?negotiateVersion=1 Request Method: OPTIONS Status Code: 405 Not Allowed Remote Address: 10.11.111.4:443 Referrer Policy: strict-origin-when-cross-origin
I tried allowing specific origins, all origins and every possible CORS related options i found. I doubt i am messing up with the order somewhere?
Below is Program.cs code
using System.IdentityModel.Tokens.Jwt;
using DotNetSmartLogger;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.OpenApi.Models;
using NLog;
using NLog.Web;
using Quality.EightD.API;
using Quality.EightD.API.Behaviour;
using Quality.EightD.API.ChatHub;
var builder = WebApplication.CreateBuilder(args);
// QA Appsetting testing
//builder.Configuration
// .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true);
// Add services to the container.
builder
.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
});
builder
.Services.AddSignalR(hubOptions =>
{
hubOptions.EnableDetailedErrors = true;
hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(15); // Reduce from 1 minute
hubOptions.ClientTimeoutInterval = TimeSpan.FromSeconds(30); // Reduce from 2 minutes
hubOptions.HandshakeTimeout = TimeSpan.FromSeconds(15); // Add handshake timeout
hubOptions.MaximumReceiveMessageSize = 102400; // Increased to 100KB
hubOptions.StreamBufferCapacity = 10;
})
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.PropertyNamingPolicy = null;
});
builder.Services.AddCors(options =>
{
options.AddPolicy(
"CORSPolicy",
builder =>
{
builder
.WithOrigins("http://localhost:8080", "https://test.test.test.com")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}
);
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.ConfigureRepositories();
builder.Services.AddSwaggerGen(setup =>
{
// Include 'SecurityScheme' to use JWT Authentication
var jwtSecurityScheme = new OpenApiSecurityScheme
{
Scheme = "bearer",
BearerFormat = "JWT",
Name = "JWT Authentication",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Description = "Put **_ONLY_** your JWT Bearer token on textbox below!",
Reference = new OpenApiReference
{
Id = JwtBearerDefaults.AuthenticationScheme,
Type = ReferenceType.SecurityScheme,
},
};
setup.SwaggerDoc("v1", new OpenApiInfo { Title = "Quality.EightD.API", Version = "v1" });
setup.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme);
setup.AddSecurityRequirement(
new OpenApiSecurityRequirement { { jwtSecurityScheme, Array.Empty<string>() } }
);
});
// Configure smart logger
builder.Services.AddLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
loggingBuilder.AddNLogWeb();
});
// Configure Kestrel server options
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = long.MaxValue; // if don't set default value is: 30 MB
});
// Configure form options
builder.Services.Configure<FormOptions>(o =>
{
o.ValueLengthLimit = int.MaxValue;
o.MultipartBodyLengthLimit = int.MaxValue;
o.MultipartBoundaryLengthLimit = int.MaxValue;
o.MultipartHeadersCountLimit = int.MaxValue;
o.MultipartHeadersLengthLimit = int.MaxValue;
o.BufferBodyLengthLimit = int.MaxValue;
o.BufferBody = true;
o.ValueCountLimit = int.MaxValue;
});
builder.Services.AddHttpContextAccessor();
// Configure JWT Authentication
builder
.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (
(
!string.IsNullOrEmpty(accessToken)
|| context.Request.Headers.ContainsKey("Authorization")
) && path.StartsWithSegments("/chatHub")
)
{
context.Token = accessToken;
}
return Task.CompletedTask;
},
};
options.RequireHttpsMetadata = false; // For development - set to true in production
options.SaveToken = true;
});
var app = builder.Build();
// Configure Swagger
app.UseSwagger(c =>
{
c.RouteTemplate = "eightd-api-svc/{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/eightd-api-svc/v1/swagger.json", "API Service V1");
c.RoutePrefix = "eightd-api-svc";
c.ConfigObject.AdditionalItems["syntaxHighlight"] = new Dictionary<string, object>
{
["activated"] = false,
};
});
LogManager.Configuration.Variables["logPath"] = builder.Configuration.GetValue<string>("logPath");
// Update the order of middleware
// First, essential middleware
app.UseRouting();
app.UseCors("CORSPolicy");
app.UseAuthentication();
app.UseAuthorization();
// Add buffering middleware early in the pipeline
app.Use(
async (context, next) =>
{
// Enable buffering for all requests
context.Request.EnableBuffering();
await next();
}
);
// Then your custom middleware
app.UseMiddleware<JwtAuthenticationBehaviour>();
app.UseMiddleware<ResponseMiddleware>();
app.UseMiddleware<NLogRequestPostedBodyMiddleware>();
app.UseMiddleware<SmartLoggingMiddleware>();
app.UseMiddleware<ExceptionHandlingMiddleware>();
// Finally endpoints
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<ChatHub>("/chatHub");
});
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
Issue :
// Finally endpoints
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<ChatHub>("/chatHub");
});
Fix :
// Finally endpoints
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<ChatHub>("eightd-api-svc/chatHub");
});