0

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();
6
  • Please try to comment this line //app.UseHttpsRedirection();, then check again. Commented Mar 21 at 2:26
  • May I know where you host the application, IIS or others? If you are using IIS, could you kindly check URL Rewrite module is installed or not, thanks~ Commented Mar 21 at 4:46
  • This service is hosted on ARO. Commented Mar 21 at 5:28
  • Hi Ishan, what is ARO ? Could you share me the link ? Commented Mar 21 at 6:22
  • Sorry, its Azure Red Hat OpenShift. Commented Mar 21 at 18:22

1 Answer 1

0

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");
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.