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

org.eclipse.ecf.provider.filetransfer.httpclientjava does not support proxy authentication #76

Open
merks opened this issue Nov 11, 2023 · 14 comments

Comments

@merks
Copy link
Contributor

merks commented Nov 11, 2023

See the following p2 issue for background details:

eclipse-equinox/p2#381

It's not clear (to me) if the proxy needs to be configured by java.net.http.HttpClient.Builder.proxy(ProxySelector) as suggested here:

https://openjdk.org/groups/net/httpclient/intro.html

Note that with org.eclipse.ecf.internal.provider.filetransfer.httpclientjava.Activator.USE_SHARED_CLIENT_DEFAULT being true, I think there is only a singe HttpClient that is shared.

These two fields

@SuppressWarnings("unused")
private static final List<String> DEFAULT_PREFERRED_AUTH_SCHEMES_NO_NTLM = Arrays.asList("Basic","Digest");
@SuppressWarnings("unused")
private static final List<String> DEFAULT_PREFERRED_AUTH_SCHEMES = Arrays.asList("Basic", "Digest", "NTLM");

which are copied from here:

private static final List<String> DEFAULT_PREFERRED_AUTH_SCHEMES_NO_NTLM = Arrays.asList("Basic","Digest");
private static final List<String> DEFAULT_PREFERRED_AUTH_SCHEMES = Arrays.asList("Basic", "Digest", "NTLM");

are not actually used. It's not clear what, if anything, needs to be configured in this regard.

The following implementation detail is clearly incomplete:

Perhaps it would be correctly implemented like this:

Credentials credentials = getCredentials(new AuthScope(getRequestingHost(), getRequestingPort()));

It's possible that if this were fixed, some additional proxy configurations would "just work"...

@scottslewis
Copy link
Contributor

The following implementation detail is clearly incomplete:

Perhaps it would be correctly implemented like this:

Credentials credentials = getCredentials(new AuthScope(getRequestingHost(), getRequestingPort()));

It's possible that if this were fixed, some additional proxy configurations would "just work"...

I agree with @merks that this might fix some (or even all) of the observed proxy creds regressions. I have no way of testing whether it will help or not however, so we should line up some testing assistance and/or environment before making this fix.

@SebasHein
Copy link

I am one of the users behind an authentification proxy.
I know you would prefere some kind of unit test work environment but thats apparently hard to set up.

If you could provide me with a build of the eclipse sdk that contains the fix @merks suggests, I could do a test and see wether it works again - if that is of any help of course.

@merks
Copy link
Contributor Author

merks commented Nov 13, 2023

Yes, my sense is that the fix can do no harm. In fact the called getCredentials method looks to me highly likely to produce NPEs when passed null as it current does so I feel we should change this regardless of there not being good automated tests...

@SebasHein

Locally for testing this technology stack, I use the installer with these projects for the workspace:

image

That lets me change and test everything (ECF, p2, and Oomph) locally.

If you wish to help with testing such a change before there is an ECF build, let's discuss that further in this Oomph issue that I just opened:

eclipse-oomph/oomph#46

Thanks again for reporting the issue...

merks added a commit to merks/ecf that referenced this issue Nov 14, 2023
Ensure that httpclientjava's
HttpClientProxyCredentialProvider.getCredentials(AuthScope) is called
with a correct AuthScope from getPasswordAuthentication.

Also update some target platform dependencies for the 2022-03 target to
use the most recently released versions of client5/core5.  Focus
particularly on what is required by the httpclient5 feature because
that's pulled into p2 and hence almost all installations, e.g., it does
not need to include org.apache.commons.logging and should use the latest
org.apache.commons.commons-codec rather than org.apache.commons.codec.

eclipse#76
eclipse#77
@merks
Copy link
Contributor Author

merks commented Nov 14, 2023

@SebasHein

I produced this update site that you could use for testing the potential fix:

https://ci.eclipse.org/emf/job/test-ecf/lastSuccessfulBuild/artifact/releng/org.eclipse.ecf.releng.repository/target/repository/

@sratz
Copy link
Contributor

sratz commented Nov 16, 2023

I have looked into this in more detail and have come to the conclusion that the implementation is incomplete regarding proxy authentication.

The whole code base of java 11 client was copied from apache http client 5 and adapted.

However, apache 5 worked significantly different:

The Java 11 HTTP client however, does not allow request-specific credential providers or proxy selectors. It only allows a global one set on the HttpClient instance during its construction.

The current ECF wrapper for Java 11 tries to imitate such a 'request context' object by introducing a custom interface
https://github.com/eclipse/ecf/blob/3485821a7c5c8948d8a82caca5a454a04c45607d/providers/bundles/org.eclipse.ecf.provider.filetransfer.httpclientjava/src/org/eclipse/ecf/internal/provider/filetransfer/httpclientjava/IHttpClientContext.java

and the proxy and credential information goes to the implementation of that interface:

IHttpClientContext context = new IHttpClientContext() {
private Map<String, Object> values = new HashMap<>();
@SuppressWarnings("unused")
private Authenticator authenticator;
@SuppressWarnings("unused")
private HttpHost httpHost;
@Override
public void setAttribute(String key, Object value) {
values.put(key, value);
}
@Override
public void setCredentialsProvider(Authenticator contextCredentialsProvider) {
this.authenticator = contextCredentialsProvider;
}
@Override
public Object getAttribute(String key) {
return values.get(key);
}
@Override
public void setProxy(HttpHost httpHost) {
this.httpHost = httpHost;
}
};

The problem is - as can be seen by the @SuppressWarnings("unused") - this information is simply going nowhere, because there is no notion of such a client request context in the Java 11 HTTP client.

I don't think there is an easy way around this.

Two options have come to mind:

  1. Somehow hack in this per-request-context by passing along the information in some static Map / via ThreadLocals. The problem is that the Java 11 HTTP client is async by default and we are not in the same thread in HttpClientFileSystemBrowser and in the ProxySelector / Authenticator. So there is no key for a mapping of request -> IHttpClientContext that we could leverage for a lookup.
  2. Do not re-use the HTTP client instances at all. Instead, create a fresh one for every ECF call. This probably results in worse performance, as sockets / caches cannot be shared and re-used. It also would change the public API of org.eclipse.ecf.internal.provider.filetransfer.httpclientjava / org.eclipse.ecf.provider.filetransfer.httpclientjava significantly.

@sratz
Copy link
Contributor

sratz commented Nov 16, 2023

Another thing:

The Java HTTP client - by default - disallows Basic Authentication for proxies since Java 8u111:

So after solving the problem mentioned above, we would - additionally - need the following system properties to be set:

jdk.http.auth.proxying.disabledSchemes = ""
jdk.http.auth.tunneling.disabledSchemes = ""

to get things working. This would need to happen probably via eclipse.ini, as these are initialized statically very early:
https://github.com/openjdk/jdk17u/blob/df82c1c6490bb5114fe52e4e1a4faa6aa3a56cfd/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java#L197-L216
so a System.setProperty() would probably be too late.

@laeubi
Copy link
Member

laeubi commented Nov 17, 2023

@sratz Prox Auth is done on the http level, so one always could set these headers manually (we do that at Tycho already)...

@merks
Copy link
Contributor Author

merks commented Nov 20, 2023

@scottslewis

Note that final platform build is on Wednesday so it will be good to have a final repository URL for that:

eclipse-platform/eclipse.platform.releng.aggregator#1390

Also for contribution to SimRel. If you let me know the URL I will do that for ECF.

Thanks.

@scottslewis
Copy link
Contributor

@merks

Here is release build repo for ECF 3.14.40:

https://download.eclipse.org/rt/ecf/3.14.40/site.p2/3.14.40.v20231114-1017/

@scottslewis
Copy link
Contributor

@merks @laeubi

As @laeubi appears disinclined to implement this (he is the implementer of the httpclientjava provider). I'm going to close this issue. If it should be reopened then please do so.

@jonahgraham
Copy link
Contributor

Can you consider reopening this for planning because we have started a funded dev effort initiative to cover this issue.

@scottslewis scottslewis reopened this Jun 18, 2024
@jonahgraham
Copy link
Contributor

There seems to be an open question as to which approach for handling http going forward should happen. The ECF and Equinox/p2 project teams need to decide on the correct course of action so that the planning council can recommend funding this work to the IDE WG. (See this comment in gitlab)

@merks
Copy link
Contributor Author

merks commented Jun 23, 2024

This is a related problem that I too encounter only with the newer provider:

eclipse-equinox/p2#529

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants