nats.net.v2 icon indicating copy to clipboard operation
nats.net.v2 copied to clipboard

Support setting HTTP headers for WebSocket connection

Open wolfman42 opened this issue 1 year ago • 5 comments

Proposed change

Support setting of (additional) HTTP headers for WebSocket connection. This could be a new part of NatsOpts class. Useful for providing an Authorization header. Perhaps along the following lines:

        var opts = new NatsOpts {
            Url = $"wss://localhost:8181"
        };
        opts.SetWebSocketHeader("authorization", $"Bearer {accessToken}");
        await using var nats = new NatsConnection(opts);
        await nats.PingAsync();

OnConnectingAsync callback should allow updating the headers, so that an authorization token could be refreshed.

Use case

JWT based authorization outside of NATS server.

Contribution

yes, interested.

wolfman42 avatar Jan 04 '24 22:01 wolfman42

I don't think that WebSockets support HTTP Headers. I've been frustrated by this before :smile:

https://stackoverflow.com/a/4361358

SignalR Core uses a query string parameter to transmit bearer tokens over websockets

caleblloyd avatar Jan 04 '24 23:01 caleblloyd

I don't think that WebSockets support HTTP Headers. I've been frustrated by this before 😄

https://stackoverflow.com/a/4361358

SignalR Core uses a query string parameter to transmit bearer tokens over websockets

WebSockets in C# (and most other languages / frameworks) do support HTTP headers. The only situation when it's not supported (AFAIK) is when you try to connect a WebSocket from a browser application.

Here's a C# example:

            using (var socket = new ClientWebSocket())
                try
                {
                    socket.Options.SetRequestHeader("authorization", $"Bearer {accessToken}");
                    await socket.ConnectAsync(new Uri($"wss://localhost:8181"), CancellationToken.None);

                    await Send(socket, "data");
                    if (!await Receive(socket)) return;

                }
                catch (Exception ex)
                {
                    Console.WriteLine($"ERROR - {ex.Message}");
                    return;
                }

wolfman42 avatar Jan 04 '24 23:01 wolfman42

Good to know. Maybe we could have a callback in NatsOpts:

Func<Uri, ValueTask<ClientWebSocketOptions>>? ConfigureWebSocketOpts

Where the Uri argument is the URI of the NATS Server we are attempting to connect to

caleblloyd avatar Jan 04 '24 23:01 caleblloyd

👍 I could see this being extremely useful with Blazor WebAssembly, specifically with being able to securely emit events from the frontend without the need for SignalR

adamreed90 avatar Mar 07 '24 02:03 adamreed90

I think that Blazor WebAssembly running in the browser will use the Browser's websocket implementation, which doesn't support headers.

caleblloyd avatar Mar 07 '24 02:03 caleblloyd