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 {
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);