I am trying to create an app that provide Api methods and SignalR hub connection to authorized clients using microservices architecture. We are using reference token with Identity Server. Identity Server is another project and runs standalone, so my application must authorize a user through Identity Server and get his Claims. I am getting errors when clients are trying to start a socket connection.
Server:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder
.WithOrigins("https://localhostClientUrl")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddAuthentication(OAuth2IntrospectionDefaults.AuthenticationScheme)
.AddOAuth2Introspection(options =>
{
options.Authority = "https://identityserverURL";
options.ClientId = "client";
options.ClientSecret = "secret";
options.Events = new OAuth2IntrospectionEvents
{
OnTokenValidated = async context =>
{
var path = context.HttpContext.Request.Path;
var accessToken = context.Request.Query["access_token"];
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments(Configuration["MapHub"])))
{
// Read the token out of the query string
context.SecurityToken = accessToken;
}
await Task.CompletedTask;
}
};
});
also
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapHub<ChatHub>(Configuration["MapHub"]);
});
Client:
this.hubConnection = new signalR.HubConnectionBuilder()
.withUrl(this.hubUrl, { accessTokenFactory: () => "ReferenceToken" })
.withAutomaticReconnect()
.build();
this.hubConnection
.start()
.then(() => {
return true;
})
.catch((err) => {
return false;
});
The client is successfully connected and can get all claims on HttpContext.User for the current connection. Prior successful connection i am receiving many clients errors:
WebSocket connection to 'wss://localhost:2222/myHub?id=ew5CRILwAiTZ955IXCZEkg&access_token=C11235C6ADEA27B5EABC08762E1A1B65077278714' failed: HTTP Authentication failed; no valid credentials available
Error: Failed to start the transport 'WebSockets': Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.
GET https://localhost:2222/myHub?id=XaHhJ66drE0tfIlI3-_OPA&access_token=C11235C6ADEA27B5EABC08762E1A1B65077278714 401
Error: Failed to start the transport 'ServerSentEvents': Error: EventSource failed to connect. The connection could not be found on the server, either the connection ID is not present on the server, or a proxy is refusing/buffering the connection. If you have multiple servers check that sticky sessions are enabled.
Any ideas? I see that client is sending /myHub/negotiate requests to the server. Also OnTokenValidated the context.Request.Query["access_token"] is empty. What do i miss?
If i change the AddOAuth2Introspection and use AddIdentityServerAuthentication which is deprecated is working wihtout any client errors.
.AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options =>
{
// base-address of your identityserver
options.Authority ="https://identityserverURL";
options.ApiName = "apiname";
options.ApiSecret = "secret";
options.RequireHttpsMetadata = false;
options.TokenRetriever = new Func<HttpRequest, string>(req =>
{
var fromHeader = TokenRetrieval.FromAuthorizationHeader();
var fromQuery = TokenRetrieval.FromQueryString();
return fromHeader(req) ?? fromQuery(req);
});
});
Thank you