nats-io / nats.java

Java client for NATS
Apache License 2.0
563 stars 153 forks source link

Authenticated Proxy support for WebSocket client #853

Open GrafBlutwurst opened 1 year ago

GrafBlutwurst commented 1 year ago

Feature Request

I am currently in the situation that I'd like to connect to NATS from behind an authenticated HTTP Proxy. And while the library handles proxying just fine, it can't handle authenticated proxies.

Use Case: The WebSocket Client can already handle proxies but not if it's an HTTP Proxy requiring authentication during CONNECT

Proposed Change:

Essentially here (https://github.com/nats-io/nats.java/blob/ba5dd0d85e7cec015e5d05c4cd44c95be0399ec1/src/main/java/io/nats/client/support/WebSocket.java#L53) the new code would need to handle authentication required proxy responses and react accordingly by sending the required headers as part of a CONNECT request.

Who Benefits From The Change(s)?

Mainly people who're in the same situation i am, that is WebSocket + Authed Proxy

Alternative Approaches

I attempted to do this myself by slightly abusing the ability to set the DataPort class on the connection builder. However I noticed that the NatsConnection that is part of the parameters of said interface is only packaged scope, so I can't override it either.

scottf commented 1 year ago

Can you make your change in the same package? I think this would be a useful contribution to the project.

GrafBlutwurst commented 1 year ago

So I started digging into it, however my implementation plan doesn't work.

In presence of an http Proxy the new Socket that is created in SocketDataPort actually creates an HttpConnectSocketImpl underneath. This means at the point where we are on the WebSocket. This will do the http CONNECT as part of the sockets connect and in WebSocket it's too late and the socket is already closed because we got a 407 response.

HttpConnectSocketImpl uses HttpUrlConnection internally and sets the proxy there but at least in Java 8 (the buildtarget of this project) the Socket does not support setting a specific Authenticator. Since Java 9 HttpUrlConnection does permit to do so, so maybe it'd be possible on a higher build target?

Anyway, what at least works due to the way the Java internal Sockets are wired is to set the system wide Authenticator using Authenticator.setDefault which i really wanted to avoid.

So I'm out of ideas sadly, if someone has a better idea to tackle this let me know and I'll give it another crack.

scottf commented 2 months ago

@GrafBlutwurst Can you see if this change, released in 2.18.0, fixes your issue? Change: https://github.com/nats-io/nats.java?tab=readme-ov-file#reverse-proxy