Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot login through the Connect plugin on http site #832

Closed
mmuzikar opened this issue Mar 22, 2024 · 13 comments
Closed

Cannot login through the Connect plugin on http site #832

mmuzikar opened this issue Mar 22, 2024 · 13 comments
Assignees
Labels
area/connect kind/enhancement Enhancements that don't necessarily result in a new feature kind/ux Issues relating to user experience
Milestone

Comments

@mmuzikar
Copy link
Contributor

Currently it's impossible to login through insecure context. When trying to login the window.crypto.subtle object is undefined:
image

Either hawtio should not work in insecure context at all (which is IMO the worse option) or hawtio should also work in insecure context.

Note: localhost or 127.0.0.1 is considered safe by the browser so the subtle object is present, but when even on the PC's IP such as http://192.168.0.143:3000/hawtio/ the website is considered insecure and the object is missing. And there's no note about it, the button just doesn't do anything for the user.

@tadayosi tadayosi added kind/enhancement Enhancements that don't necessarily result in a new feature area/connect kind/ux Issues relating to user experience labels Mar 25, 2024
@tadayosi
Copy link
Member

The Connect plugin's capability to connect to a remote JVM with BASIC authentication is now supported only when Hawtio is running on localhost or secured with HTTPS. This requirement is due to the limitation that Web Crypt API is only available in secure contexts:
https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

What we can do is to provide the user better UI feedback when they are trying to use the Connect plugin over BASIC authentication in an insecure way, which might lead to compromise the credentials over an insecure channel and thus is not supported.

@tadayosi
Copy link
Member

FYI, the issue is caused by support for secure session storage at #760.

@grgrzybek
Copy link
Contributor

Somehow, even on http://localhost, browser can add the Authorization header to jolokia proxy requests after displaying browser's native popup (to get Basic credentials).

I've created #910 because I was able to broke something and I have to dig deeper.

@mmuzikar
Copy link
Contributor Author

http://localhost is considered secure for development purposes (i guess :D) but http:// (other than 127.0.0.1) isn't.

@grgrzybek
Copy link
Contributor

grgrzybek commented Apr 30, 2024

@mmuzikar @tadayosi I can't determine exactly when this dialog shows up...
In my tests (Hawtio running on Tomcat, Spring Boot or just app/ with yarn start) I could use connect tab connect to self (setting the same address and jolokia path from WAR) or to my external Jolokia agent with Basic authentication configured.

Usually browser-native popup appears like this:
image

But sometimes I really saw the React dialog for entering credentials. I didn't check the session storage at that time.

I was really looking for the effects of using crypto to store the credentials in session storage, but I didn't see it when naive browser popup appeared.

I did some tests on http://localhost, different ports. I was building my own node:http server, express.js server proxying requests to esbuild --serve to check different combinations (didn't catch'em all yet) and here are some of my observations:

  • Hawtio never truly (please confirm @tadayosi) does real Jolokia cross-origin requests. Actual xhr requests are sent to remote agent through Hawtio proxy running on the same origin
  • if it'd be otherwise, xhr's withCredentials or fetch credentials options decide whether or not to display the native dialog
  • When using remote Jolokia through Hawtio connect and if the proxy (whether real ProxyServlet or hawtio-middleware or my custom app.all('/hawtio/jolokia*', (req, res) => { ...) handles 401/403/WWW-Authenticate correctly, I could trigger the native browser dialog to enter credentials
  • returning WWW-Authenticate for /proxy and /jolokia requests may mess things up when browser decides to store your credentials, as these are stored per origin and realm. I really once did something which caused bad credentials to be sent for /jolokia and resulting 403 lead to logout. I don't remember how I saved bad credentials, but I've opened Remote connection to authenticated Jolokia may cause endless redirect loop #910 to investigate
  • the funny aspect is that if you get the native popup and enter any credentials (good or bad), you can see the request in network tab, but without Authorization header. Only next (after successful authentication) request shows the header. However in Wireshark you see this header for both requests.

Do you know how to ensure that React dialog (<ConnectLogin>) is shown instead of native browser dialog for remote connection?

@grgrzybek
Copy link
Contributor

grgrzybek commented May 6, 2024

Comment moved to #910 (comment)

@tadayosi
Copy link
Member

tadayosi commented May 7, 2024

@grgrzybek Thanks for your detailed report. However, at this moment, it appears to me a different issue than the original one, as the original issue doesn't get involved with the browser native prompt. Maybe it's better to discuss it further with a separate issue, as it may require a different fix.

@grgrzybek
Copy link
Contributor

For the record, when using /proxy endpoint, we're doing same-origin requests and:

  • with xhr we can't decide about sending Authorization header and withCredentials option is ignored:

Setting withCredentials has no effect on same-origin requests

  • with fetch API, we can use credetntials option to decide about sending the credentials

With XHR (used by Jolokia) every time an attempt is made and we didn't specify the credentials in browser-native popup, the popup will be redisplayed. Once the credentials are entered, the popup won't show until we clear "Active logins".

With fetch API, if we'd use explicit credentials: 'omit' we could test for 401 and display React dialog to enter the credentials. BTW - this is exactly what happens if we explicitly close the native popup when connecting to remote Jolokia where /proxy returns proxied 401.

@grgrzybek
Copy link
Contributor

grgrzybek commented May 10, 2024

When checking connections on http and my ip address different than 127.0.0.1 I see some weird issues with hanged connection.
Seems like hawtioMiddleware returns CanceledError: Request stream has been aborted sometimes and then I can see Jolokia agent hanged waiting for some data on JDK HTTP incoming requests... Checking.

"jolokia-0" #21 daemon prio=5 os_prio=0 cpu=77,11ms elapsed=562,51s tid=0x00007f95d401d660 nid=0x12c02 runnable  [0x00007f96a6af4000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.SocketDispatcher.read0(java.base@17.0.11/Native Method)
	at sun.nio.ch.SocketDispatcher.read(java.base@17.0.11/SocketDispatcher.java:47)
	at sun.nio.ch.IOUtil.readIntoNativeBuffer(java.base@17.0.11/IOUtil.java:330)
	at sun.nio.ch.IOUtil.read(java.base@17.0.11/IOUtil.java:296)
	at sun.nio.ch.IOUtil.read(java.base@17.0.11/IOUtil.java:259)
	at sun.nio.ch.SocketChannelImpl.read(java.base@17.0.11/SocketChannelImpl.java:417)
	at sun.net.httpserver.Request$ReadStream.read(jdk.httpserver@17.0.11/Request.java:287)
	- locked <0x000000062de66bf0> (a sun.net.httpserver.Request$ReadStream)
	at java.io.BufferedInputStream.fill(java.base@17.0.11/BufferedInputStream.java:244)
	at java.io.BufferedInputStream.read1(java.base@17.0.11/BufferedInputStream.java:284)
	at java.io.BufferedInputStream.read(java.base@17.0.11/BufferedInputStream.java:343)
	- locked <0x000000062de66bc8> (a java.io.BufferedInputStream)
	at sun.net.httpserver.FixedLengthInputStream.readImpl(jdk.httpserver@17.0.11/FixedLengthInputStream.java:59)
	at sun.net.httpserver.LeftOverInputStream.read(jdk.httpserver@17.0.11/LeftOverInputStream.java:99)
	- locked <0x000000062de6f620> (a sun.net.httpserver.FixedLengthInputStream)
	at java.io.FilterInputStream.read(java.base@17.0.11/FilterInputStream.java:106)
	at sun.net.httpserver.AuthFilter.consumeInput(jdk.httpserver@17.0.11/AuthFilter.java:56)
	at sun.net.httpserver.AuthFilter.doFilter(jdk.httpserver@17.0.11/AuthFilter.java:74)
	at com.sun.net.httpserver.Filter$Chain.doFilter(jdk.httpserver@17.0.11/Filter.java:98)
	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(jdk.httpserver@17.0.11/ServerImpl.java:853)
	at com.sun.net.httpserver.Filter$Chain.doFilter(jdk.httpserver@17.0.11/Filter.java:95)
	at sun.net.httpserver.ServerImpl$Exchange.run(jdk.httpserver@17.0.11/ServerImpl.java:820)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.11/ThreadPoolExecutor.java:1136)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.11/ThreadPoolExecutor.java:635)
	at java.lang.Thread.run(java.base@17.0.11/Thread.java:842)

EDIT: - it's about using application/json vs text/json with Fetch API sending POST to Jolokia

@tadayosi
Copy link
Member

When checking connections on http and my ip address different than 127.0.0.1

If the connection is authenticated, you cannot use http with a hostname/ip address other than localhost/127.0.0.1.

@grgrzybek
Copy link
Contributor

grgrzybek commented May 13, 2024

When connecting directly to Jolokia agent with Basic auth enabled, both invocations work:

curl -u grgr:grgr 'http://localhost:7778/jolokia/' -X POST -H 'Content-Type: text/json' -H 'Content-Length: 18' -d '{"type":"version"}'

curl -u grgr:grgr 'http://localhost:7778/jolokia/' -X POST -H 'Content-Type: application/json' -H 'Content-Length: 18' -d '{"type":"version"}'

When connecting via hawtioMiddleware proxy, this works:

curl -u grgr:grgr 'http://localhost:3000/hawtio/proxy/http/localhost/7778/jolokia/' -X POST -H 'Content-Type: text/json' -H 'Content-Length: 18' -d '{"type":"version"}'

it's visible in Wireshark:
image

but this fails:

curl -u grgr:grgr 'http://localhost:3000/hawtio/proxy/http/localhost/7778/jolokia/' -X POST -H 'Content-Type: application/json' -H 'Content-Length: 18' -d '{"type":"version"}'

now backend communication in Wireshark:
image

The error is:

error proxying to "http://localhost:7778/jolokia/: CanceledError: Request stream has been aborted

@tadayosi I know it's again a bit off topic, but maybe there's something wrong with hawtioMiddleware - I'm not yet that familiar with webpack's server + axios client.

@grgrzybek
Copy link
Contributor

I can display this warning. WDYT @tadayosi @mmuzikar ?
image

grgrzybek added a commit that referenced this issue May 15, 2024
…t" (fixes #832)

Signed-off-by: Grzegorz Grzybek <gr.grzybek@gmail.com>
@grgrzybek
Copy link
Contributor

I'll at some point add a documentation section about "Connect" plugin (dedicated (sub)chapter?), but here's a little summary:

For non-secure browsing contexts there's a warning on the connect page:
image

List of configured connections may display yellow icons and the "Connect" button is disabled:
image

And finally when editing a connection to secured Jolokia in non-secure browsing context, we can see the error:
image

There are also some enhancements in secure contexts

we display some more details when testing connection:
image

we display current connection after connecting to remote agent:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/connect kind/enhancement Enhancements that don't necessarily result in a new feature kind/ux Issues relating to user experience
Projects
Archived in project
Development

No branches or pull requests

3 participants