My JavaScript SignalR client routinely connects to my asp.net core implementation of IdentityServer4.
On the client I see:
Information: WebSocket connected to wss://localhost:5001/signal/satellite?
idsrv.session=4ec93d2f4c3b9a970ff82a537ae04d97&id=0eUBg2-xobp4CNttuIQJcg
But, it also doesn't connect much of the time, with an error that there was an unexpected token in JSON at position 0.
It seems like it runs well for a bit and then poorly, even if I re-login, it still throws the error. In the browser, the call always looks more or less like:
https://localhost:5001/signal/satellite?
idsrv.session=89364018a975e4fefff9ad0869b1ae09
I don't seem to need the middleware for it to move the querystring value into the header, I still get the user in my hub during onConnect with their sub claim, etc. However, if I do put in the middleware before app.UseAuthentication() and watch for:
context.Request.QueryString.Value
when it successfully handshakes with the server, I see:
idsrv.session=89364018a975e4fefff9ad0869b1ae09
but when it doesn't, I see this:
?client_id=internal&redirect_uri=https%3A%2F%2Flocalhost%3A5001%2Fsignin-oidc&response_type=code%20id_token&scope=openid%20profile%20offline_access%20Harvey&response_mode=form_post&nonce=636817245670169226.ZWM2OWQ0ZWEtOTQzMC00YTJlLWI4MzQtYmIxZDZjOWVlYjg5ZTA4NTU2M2QtNjczZi00MTlmLThjYmQtZWUzZTQ1ODMzNDQ0&state=CfDJ8MCxOjJiJLdKqZrnPwOHDhqMnzWz6MqRb03SxToClqQ1F3n9g8yLdW683HRpZSHd-5wkN-6je4tHJkA8sc5i6YoKRxtMHwnWqxVW5-nXFaaH0TfOLUeqfxDzXLxnftmWFXLjK3Y7b6R2WzcDLEjChU1_Fk6X64SAHNRqeizGDPzRhxpV0U5w19Bbt7pUyRbYymn2WNedCS1F7g_wtwtJXDjCzWKBxqvPZ5Dtg99gxKkANalKYs7C4-fm7YdD0gFvsuV4CXsu0T06MjzID_zpA_F7TmSue4vGI-0_qY55Swc5mbLWUwKHtj6ZTfOG4UmTEP_hbj2PO9w2oNg9TWqTPtDC3-qSl1fTUkY0EtCwbA7F&x-client-SKU=ID_NETSTANDARD1_4&x-client-ver=5.2.0.0
so I'm stuck either not needing to do it because it succeeds on its own or the querystring never makes it to the middleware to move over (which is probably why it can't do it on its own)
What am I missing for it to consistently work?
Add Hybrid Client to IdentityServer4:
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
},
AllowOfflineAccess = true
}
and then in startup on the mvc client:
ServiceCollection.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "https://localhost:5001";
options.RequireHttpsMetadata = false;
options.ClientSecret = "secret";
options.ClientId = "mvc";
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("offline_access");
options.Scope.Add("api1");
options.ClaimActions.MapJsonKey("website", "website");
});
This is modeled after the example: Quickstart5_HybridAndApi
In SignalR on server:
[Authorize]
public class SignalRSignalHub : Hub
{
public override Task OnConnectedAsync()
{
var context = Context.GetHttpContext();
return base.OnConnectedAsync();
}
}
SignalR JavaScript Client:
self.signalRConnection = new signalR.HubConnectionBuilder()
.withUrl("/signal/satellite?" + document.cookie).build();