Amit Vig
Amit Vig

Reputation: 185

SignalR negotiate preflight request fails

I have a scenario where my SignalR server and Client cannot run within the same origin because we would like to share the SignalR server for more than one origin. When i run the server locally and spin up an instance of a web based signalR client running within typescript i can connect and everything works. When i move my server to Azure and use the same locally running signalR client to connect to the server i get preflight request does'nt pass access control check. There are no CORs settings in the Azure app service. All the Cors settings are done in the server code. Code below.

The error i get in the browser is : Access to XMLHttpRequest at 'https://******.azurewebsites.net/chatHub/negotiate?negotiateVersion=1' from origin 'https://localhost:44392' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request. This works as expected locally but ends up not working correctly when running in Azure and connecting from a local client.

To Reproduce

public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options => options.AddPolicy("MyCorsPolicy", builder =>
            {
                builder
                  .AllowAnyHeader()
                  .WithOrigins("https://localhost:44392/")
                  .SetIsOriginAllowed(origin =>
                  {
                      if (string.IsNullOrWhiteSpace(origin))
                          return false;

                      if (origin.ToLower().StartsWith("https://localhost"))
                          return true;
                      return false;
                  })
                  .AllowAnyMethod()
                  .AllowCredentials();
            }));
            ... //Authentication etc
            services.AddSignalR(hubOptions =>
            {
                hubOptions.EnableDetailedErrors = true;
            }).AddJsonProtocol();
        }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseRouting();
            app.UseCors("MyCorsPolicy");
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseHttpsRedirection();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Ping!");
                });
                endpoints.MapHub<ChatHub>("/chatHub");
            });
         }

In the typescript client i make the request as follows :

const connection = new HubConnectionBuilder()
        .withUrl("https://******.azurewebsites.net/chatHub" , { accessTokenFactory: () => "TOKEN GOES HERE"})
        .configureLogging(LogLevel.Information)
        .build();

Further technical details

Upvotes: 2

Views: 1655

Answers (1)

Amit Vig
Amit Vig

Reputation: 185

Marking this issue as closed. This was tricky because it worked locally but did not work in Azure. After going over the application logs and network traces @BrennanConroy noticed something related to auth was causing a redirect. I set up authentication within Azure and since that is the first thing that runs, CORS from within the app doesn't get a chance to run. The way to handle this is to use CORS within Azure but as per documentation CORS within the App service is not supported for SignalR, one should note Authentication within Azure app service will result in issues with CORS.

Upvotes: 1

Related Questions