ThreeMammals / Ocelot

.NET API Gateway
https://www.nuget.org/packages/Ocelot
MIT License
8.4k stars 1.64k forks source link

CORS policy error for just SignalR connection #1376

Closed patolax closed 5 months ago

patolax commented 4 years ago

I am trying to connect to a SignalR hub service using Ocelot gateway. Both deployed in service fabric local cluster.

The "DownstreamScheme": "http", works for in the same service, however "DownstreamScheme": "ws" fails with.

Access to XMLHttpRequest at 'http://localhost:9000/notification/negotiate' from origin 'http://localhost:7100' 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'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

So its clearly, a web socket related CORS issue. Any idea how to fix this? I using js client.

ocelot.json


{
      "DownstreamPathTemplate": "/events",
      "DownstreamScheme": "ws",
      "ServiceName": "IDCloud.Services/NotificationService",
      //"AuthenticationOptions": {
      //  "AuthenticationProviderKey": "Bearer",
      //  "AllowedScopes": [ "tenant_read" ]
      //},
      "UpstreamPathTemplate": "/notification",
      "UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ]
    },
    {
      "UpstreamPathTemplate": "/api/values",
      "UpstreamHttpMethod": [ "Get" ],
      "DownstreamPathTemplate": "/api/values",
      "DownstreamScheme": "http",
      "ServiceName": "IDCloud.Services/NotificationService",
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Bearer",
        "AllowedScopes": [ "tenant_read" ]
      }
    },

Client code

signalR.HubConnectionBuilder()
      .withUrl(url, { accessTokenFactory: () => token })
      .configureLogging(signalR.LogLevel.Information)
      .build();

Gateway code

 services.AddCors();

 app.UseCors(builder =>
            {
                builder.WithOrigins("*");
                builder.AllowAnyHeader();
                builder.AllowAnyMethod();
            });
patolax commented 4 years ago

I was able to resolve this after changing cors to my client url builder.WithOrigins(corsOrigins) .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials());

But now I get this WebSocketTransport.js:70 WebSocket connection to 'ws://localhost:9000/events?id=RhPYIkQl7s2qVcJC_ThvEw&access_token=eyJ0eXAiOiJKV1QiLCJhbG...' failed: Error during WebSocket handshake: Unexpected response code: 200

I also added to ocelot AddJwtBearer configuration OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; if (!string.IsNullOrWhiteSpace(accessToken)) { context.Token = accessToken; } return Task.CompletedTask; },

raman-m commented 5 months ago

Authentication and Authorization are not implemented in Ocelot for Websockets :exclamation: Our Web socks pipeline is quite short: https://github.com/ThreeMammals/Ocelot/blob/8c0180a6461984ebd11ceca5544ca9d0e1564975/src/Ocelot/Middleware/OcelotPipelineExtensions.cs#L37-L47

raman-m commented 5 months ago

Duplicate of #1040