-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Authentication with SignalR #1040
Comments
Definitely interested by it, that's the only issue in my architecture :-( |
I guess the easiest way up till now, is to abstract SignalR from your service and deploy it as a separate one, without the use of a gateway, since .netcore provides token authentication for SignalR. |
I do, however, I'm forced to have a second port open on the server, which is complicated on prod. Better have only the 443 to get through the firewall :-( |
@zee85 I'm planning architecture for the next project and I want to use Ocelot and SignalR. |
@zee85 thank you for sharing 🙂 I saw in ocelot docs that it doesn't handle authentication for SignalR (WebSockets). Hopefully, someday it will |
Can anyone point me to how the identityserver and signal r authentication works? I thought signalr only supported basic auth? :o I might be behind the times as have not worked much in dotnet recently :) |
Here is an example of what I have been using with my Hubs project: services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
// base-address of your identityserver
options.Authority = Configuration["IdentityServer:Url"];
// name of the API resource
options.ApiName = Configuration["IdentityServer:APIName"];
options.ApiSecret = Configuration["IdentityServer:APISecret"];
options.EnableCaching = true;
options.CacheDuration = TimeSpan.FromMinutes(10); // that's the default
options.RequireHttpsMetadata = Convert.ToBoolean(Configuration["IdentityServer:RequireHttpsMetadata"]);
// For SignalR
options.TokenRetriever = new Func<HttpRequest, string>(req =>
{
var fromHeader = TokenRetrieval.FromAuthorizationHeader();
var fromQuery = TokenRetrieval.FromQueryString();
return fromHeader(req) ?? fromQuery(req);
});
}); Taken from here Hope this helps. |
Any updates? Best, Marios. |
@mkanakis because this feature is not available right now, and I want to implement a similar thing in my project, did you use any other methods to solve this (like using reverse proxy or other different tools?) |
@hsnassaad you can use nginx as a reverse proxy, signalR is going through correctly |
I managed to have my Websocket endpoint authenticated by copying some extension classes from the Ocelot project to my project in order to be able to include the Authentication and Authorization middlewares in the WebSocket middleware sub-pipeline
Also, I need to introduce some custom middleware to return 401 on Authentication/Authorization errors because the current pipeline returns 200, which is obviously not correct. I'm curious about why this functionality is not included as the Websocket endpoint is a regular HTTP endpoint. It might be that I'm looking at it with my specific case in mind and don't get the whole picture. |
@alex-pollan please upload complete code |
The code I'm working on below. Ocelot version 16.0.1. ocelot.json "Routes": [
{
"UpstreamPathTemplate": "/hub/update/{deviceName}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ],
"DownstreamScheme": "ws",
"DownstreamPathTemplate": "/update",
"DownstreamHostAndPorts": [ { "Host": "{SignalRService}" } ],
"RouteIsCaseSensitive": false,
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [ "the_scope" ]
},
"RouteClaimsRequirement": {
"client_id": "{deviceName}"
}
}] Startup.cs public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseAuthentication();
app.UseAuthorization();
...
app.UseOcelotWebSockets();
app.UseOcelot().Wait();
} Some extension methods class public static IApplicationBuilder UseOcelotWebSockets(this IApplicationBuilder appBuilder)
{
appBuilder.UseWebSockets();
//Override Ocelot Websockets pipeline to support authentication and authorization
appBuilder.MapWhen(httpContext => httpContext.WebSockets.IsWebSocketRequest,
wenSocketsApp =>
{
wenSocketsApp.UseDownstreamContextMiddleware();
wenSocketsApp.UseExceptionHandlerMiddleware();
wenSocketsApp.UseResponderMiddleware();
wenSocketsApp.UseDownstreamRouteFinderMiddleware();
wenSocketsApp.UseMultiplexingMiddleware();
wenSocketsApp.UseHttpHeadersTransformationMiddleware();
wenSocketsApp.UseDownstreamRequestInitialiser();
wenSocketsApp.UseAuthenticationMiddleware();
wenSocketsApp.UseClaimsToClaimsMiddleware();
wenSocketsApp.UseAuthorisationMiddleware();
wenSocketsApp.UseClaimsToHeadersMiddleware();
wenSocketsApp.UseClaimsToQueryStringMiddleware();
wenSocketsApp.UseClaimsToDownstreamPathMiddleware();
wenSocketsApp.UseLoadBalancingMiddleware();
wenSocketsApp.UseDownstreamUrlCreatorMiddleware();
wenSocketsApp.UseWebSocketsProxyMiddleware();
});
return appBuilder;
} |
Waiting for this feature. Please provide me any alternate as I need to pass access token to my signal R app. |
Our current WS pipeline is quite short ))) No authentication at all 🤣 Ocelot/src/Ocelot/Middleware/OcelotPipelineExtensions.cs Lines 37 to 47 in d6eefc8
Could we convert your experience and solution to a PR please? |
Sorry! How can we re-use your solution in Ocelot if it is based on custom setup in |
I just want to clarify that my solution above is for a pure APIGW with Ocelot that proxies the SignalR connection endpoint downstream to another service where I actually implement the SignalR server. Notice that the authentication / authorization happens and it is terminated at the APIGW layer. I capture the authenticated principal identity and pass it downstream as HTTP headers to the SignalR service to use it Here are the final Ocelot routes I needed: {
"UpstreamPathTemplate": "/signalr/negotiate",
"UpstreamHttpMethod": [ "POST" ],
"DownstreamScheme": "http",
"DownstreamPathTemplate": "/devices-hub/negotiate",
"DownstreamHostAndPorts": [ { "Host": "{DevicesHubApiService}" } ],
"RouteIsCaseSensitive": false,
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [ "myscope" ]
}
},
{
"UpstreamPathTemplate": "/signalr",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ],
"DownstreamScheme": "ws",
"DownstreamPathTemplate": "/devices-hub",
"DownstreamHostAndPorts": [ { "Host": "{DevicesHubSignalRService}" } ],
"RouteIsCaseSensitive": false,
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [ "myscope" ]
}
}, |
Your JSON looks like a life hack to forward anonymous traffic to downstream and be authorized on Ocelot's side. Your previous comments with a solution is good. And I will figure out how to reuse it when started working on #1707 |
is this implemented? If not then I'm going to do id. |
@hogwartsdeveloper You are assigned! |
@hogwartsdeveloper, best of luck to you! |
Further development after upgrade to .NET 9 ❗ |
Thanks for the good work!
New Feature
Is authentication for signalR on the plans? We are using signalR with IdentityServer4, to send data over to authenticated users, but I don't think Ocelot is supporting it currently, as stated in documentation.
Motivation for New Feature
I am not sure of people who would use signalR without user authentication.
The text was updated successfully, but these errors were encountered: