Websockets and authentication with server4 id

I use .net core 1.1 and identityserver 4 to get tokens and validate users. The web api works great by reading the token carrier from the headers and getting the user's main complaints.

Now I want to use websocket (not SignalR) to send notifications. I can open the ws: // channel (or wss), but the token is not sent with headers, so in the .net kernel I do not have user information (User Claims and Identity).

How can I authenticate a user through websocket? I did a search but did not find any useful information.

thanks

+5
source share
1 answer

There are two main problems associated with authentication in the WebSocket middleware:

Authorization must be called manually

First of all, authorization does not apply to a web socket request (since it is not a controller that can be marked with the Authorize attribute). Therefore, in the WebSocket middleware, you need to call authorization yourself. This is easily accomplished by calling the AuthenticateAsync extension method of the HttpContext object.

So, your middleware will look something like this:

 public class WebSocketMiddleware { private readonly RequestDelegate next; public WebSocketMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context) { if (!context.WebSockets.IsWebSocketRequest) { await this.next.Invoke(context); return; } AuthenticateResult authenticateResult = await context.AuthenticateAsync(OAuthValidationDefaults.AuthenticationScheme); .... }); } 

So, using the results of authentication, you can check whether the user is authenticated or not, and then access the authenticated user information.

Passing a token to a web socket request

For connections to the web slot, the default authorization header does not work, because the WebSockets JS API does not allow you to set custom parameters. To get around this limitation, the access token is often passed in the query string.

To use middleware for authentication, you need to update your authentication settings. This can basically be done by running the script as follows:

 services .AddAuthentication() .AddOAuthValidation(options => { options.Events = new OAuthValidationEvents { // Note: for Web Socket connections, the default Authorization header does not work, // because the WebSockets JS API doesn't allow setting custom parameters. // To work around this limitation, the access token is retrieved from the query string. OnRetrieveToken = context => { context.Token = context.Request.Query["access_token"]; return Task.FromResult(0); } }; }); 

The following code can be used as an example to add an access token to a web socket URL when initiating a connection:

 const protocol = location.protocol === "https:" ? "wss:" : "ws:"; const wsUri = protocol + "//" + window.location.host + "/ws" + "?access_token=" + token; this.socket = new WebSocket(wsUri); 
+6
source

Source: https://habr.com/ru/post/1266160/


All Articles