2

I'm facing an inconsistent CORS issue with SignalR in my ASP.NET Core and Angular application. On my machine, the connection works fine in Chrome but fails with a CORS error in Edge. However, for some other people, the error occurs in both Chrome and Edge, which makes the issue difficult to reproduce consistently.

Access to XMLHttpRequest at 'http://localhost:21023/signalr/negotiate?enc_auth_token=wNYmO41%2F48SHNstaLVXxHCCre29BZQl1NhC6NM3R3rzpXtPQxVzH6jEzA%2FQhXFN5tu6Fk7pO53uppm1mVXMZgxbyRVz26dnepi%2FFyB6axBY%2B6gq1GL%2BuRQgoiFUCjRN2p8w6LevViwKlHyWZZJZO1DGVSjAi1m2U%2Bog9pkHw9%2FTWnx%2BxQedi3enbqm%2FZYOXT%2FBycU4LZ4F6zlZtrxzHwExtSfELJf%2F0pBk4IITKNjDQHBqaqbtRSdePntPkQpHXvZNrJtiNNLL85J%2F82FKzVtA8QFbHGXtNOZ0fxoo2a1PXJ9tDbrwc9J%2BI7IuFSrHNNT3DC28TLcM7kBDr5mCl95lNKMDiM9hflCF7A6D%2BTSCOGKZJGV6uiFiyN1qDqLG95D4BgZchn6jC%2FSTq493ETqjromBYUfLMabD0HGtdrmMAtmjbyHHswplwmBUPw1heNZCPd%2BmVVqg7jpSio9GWs6B0MZWfI3ZTW6Ox%2BGZMPTiv5RdVDpvoNOLyQAarB0Y8sa6zhTa2mQSXFpwgLm1gfUEIY5DDrgAesHYt8DRXab%2B6Jitdbn6nKmVd0aayomDTm0TJmEG0upxcuSg0aIoYnDqauY33PPhb4L4lmOWUOu5ojBHRHAT%2BQynlt9sFSjqXcBoKmUzB2Hg6pEYRHM3Ah3XUOHDtwwxjITCL%2FKV3HFf8hFBgp%2F9rPtYVn5eziCkIoDBfyahUqpUQKQ%2FULKZvHhKIsaoVNSC0DKSKF5teOv1MIp60Te20EDcwJs6YurEXzkWFhFAAVH6%2Fb1bjDY0MQfhOTNeu9JFvHecXdkbqACrzi04714nKTZcu%2F1Zroiikf9HKJ4Ew7QmqrtNgrfLNyThON6hgpJWuz60TzSzaki7dwfYT72u7DjPel0%2B7Qsaz4VcKtVSPHZEoQVWzomMk6QlgiYkM08MUaVEdFNLBENrChUaKgvfG8G%2BhWggKGMGInp%2BuIp4OwbstyyOapAGGDhA%3D%3D' from origin 'http://localhost:4200' has been blocked by CORS policy: Request header field x-requested-with is not allowed by Access-Control-Allow-Headers in preflight response.

I have configured CORS in Startup.cs and tried several different approaches, but it still doesn’t work. I suspect the issue might be related to the middleware order or a missing Authorization header in the CORS configuration.

Backend (ASP.NET Core)

Here is the CORS and SignalR configuration in Startup.cs:

// ConfigureServices method
services.AddCors(
    options => options.AddPolicy(
        _defaultCorsPolicyName,
        builder => builder
            .WithOrigins(
                // App:CorsOrigins in appsettings.json can contain more than one address separated by comma.
                _appConfiguration["App:CorsOrigins"]
                    .Split(",", StringSplitOptions.RemoveEmptyEntries)
                    .Select(o => o.RemovePostFix("/"))
                    .ToArray()
            )
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowCredentials()
            .SetIsOriginAllowed(s => true)
    )
);

services.AddSignalR(options =>
{
    options.EnableDetailedErrors = true;
});

// Configure method
app.UseAbp(options => { options.UseAbpRequestLocalization = false; }); // Initializes ABP framework.

app.UseCors(_defaultCorsPolicyName); // Enable CORS!

app.UseStaticFiles();

app.UseAuthentication();

app.UseAbpRequestLocalization();

app.UseSignalR(endpoints =>
{
    endpoints.MapHub<AbpCommonHub>("/signalr", options => {
        options.Transports = HttpTransportType.LongPolling | HttpTransportType.WebSockets;
    });
    endpoints.MapHub<TimekeepingHub>("/signalr-timekeepingHub", options => {
        options.Transports = HttpTransportType.LongPolling | HttpTransportType.WebSockets;
    });
});

Frontend (Angular)
Here is how I connect to the SignalR hub from Angular:

setupMyTimekeepingHub(callback : Function): void {
    const self = this;
    abp.signalr.startConnection(abp.appPath + 'signalr-timekeepingHub', function (connection) {
        console.log(connection);
        self.timekeepingHub = connection; // Save a reference to the hub

        connection.on('connectedSuccess', function (prevSyncDays: string[]) {
            self.listProcessingDays = prevSyncDays;
            self.timekeepingProcess.next({event:"connectedSuccess",data: self.listProcessingDays});
        });

        // Other event handlers...
    }).then(function (connection) {
        abp.log.debug('Connected to timekeepingHub server!');
        if(typeof callback === "function"){
            callback();
        }
    }).catch((err) => {
        console.log(err);
        self.timekeepingProcess.next({event:"errorOccured",data: null});
    });
}

initSignalR(callback): void {
    const encryptedAuthToken = new UtilsService().getCookieValue(AppConsts.authorization.encrptedAuthTokenName);

    abp.signalr = {
        autoConnect: true,
        connect: undefined,
        hubs: undefined,
        qs: AppConsts.authorization.encrptedAuthTokenName + '=' + encodeURIComponent(encryptedAuthToken),
        remoteServiceBaseUrl: AppConsts.remoteServiceBaseUrl,
        startConnection: undefined,
        url: '/signalr'
    };

    jQuery.getScript(AppConsts.appBaseUrl + '/assets/abp/abp.signalr-client.js', () => {
        this.setupMyTimekeepingHub(callback);
    });
}

I have tried the following:

* Changing the middleware order (placing CORS before Authentication)
* Adding a custom middleware to handle preflight OPTIONS requests
* Adding the Authorization header to Access-Control-Allow-Headers
* Removing extra whitespaces in the URL

But it still doesn’t work. Has anyone experienced this issue before? What should I do to resolve this CORS error?

Additional information:

* ASP.NET Core version: 2.2
* SignalR version: 1.1.0
* Angular version: 8.2.14
* ABP Framework version: 4.3.0
13
  • x-requested-with is usually used by client-side frameworks to give the server an indication that this is a background request. What happens if you add that to Access-Control-Allow-Headers? Commented Aug 21 at 6:47
  • what do you mean, what is your solution? I have tried to add x-requested-with in the header list but it still not working Commented Aug 21 at 7:53
  • you might try adding RequireCors to each endpoint. See here: learn.microsoft.com/en-us/aspnet/core/security/… You may also want to simplify your CORS policy by hard-coding it instead of reading it from config file, just to rule that out. Commented Aug 21 at 16:36
  • How are you placing the Angular app? Are you placing the index.html inside the www of your .net? Commented Aug 21 at 21:29
  • @StefaniToto No, the Angular application is not placed inside the www folder of your .NET project. Instead: Frontend and backend run on separate servers The Angular frontend communicates with the backend through API calls and SignalR Commented Aug 22 at 14:36

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.