You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by "goutamadwant (via GitHub)" <gi...@apache.org> on 2026/09/16 03:53:33 UTC

[PR] Honor system proxy credentials in Apache transport [maven-resolver]

goutamadwant opened a new pull request, #2148:
URL: https://github.com/apache/maven-resolver/pull/2148

   Related to #2139.
   
   With `aether.connector.http.useSystemProperties=true`, the Apache transport uses the configured proxy but ignores its username and password, causing HTTP 407. Use matching HTTP or HTTPS system proxy credentials when explicit Resolver authentication is unavailable.
   
   Keep fallback credentials scoped to the actual proxy, separate from repository authentication. Clear their authentication state when a redirect changes proxy or becomes direct. The opt-in remains disabled by default; this adds no public API or runtime dependency.
   
   Tests cover GET/HEAD/PUT, HTTPS CONNECT, explicit credential precedence, missing or mismatched properties, origin isolation, and redirects. The native regression fails with HTTP 407 on unchanged master.
   
   Validation on Java 21 with Maven 3.9.16:
   
   - `mvn verify`: all 31 modules passed; 2,082 tests, zero failures/errors, 87 existing skips.
   - `mvn -Prun-its verify`: passed, including 107 integration tests and one Invoker build.
   - All 19 new proxy cases ran without skips.
   
   This targets Resolver 2.x. The corresponding 1.9.x backport covers the lineage used by Maven 3.9.16.
   
   - [x] The pull request addresses one issue without unrelated changes.
   - [x] The description explains what changed, how, and why.
   - [x] The commit has a meaningful subject and body.
   - [x] Regression tests fail without the runtime fix.
   - [x] `mvn verify` passed.
   - [x] `mvn -Prun-its verify` passed.
   - [ ] I hereby declare this contribution to be licenced under the [Apache License Version 2.0, January 2004](https://www.apache.org/licenses/LICENSE-2.0).
   - [ ] File an [Apache Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf), as applicable.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Honor system proxy credentials in Apache transport [maven-resolver]

Posted by "cstamas (via GitHub)" <gi...@apache.org>.
cstamas merged PR #2148:
URL: https://github.com/apache/maven-resolver/pull/2148


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Honor system proxy credentials in Apache transport [maven-resolver]

Posted by "gnodet-bot (via GitHub)" <gi...@apache.org>.
gnodet-bot commented on code in PR #2148:
URL: https://github.com/apache/maven-resolver/pull/2148#discussion_r4022365681


##########
maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SystemProxyAuthenticationStrategy.java:
##########
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.transport.apache;
+
+import java.util.Map;
+import java.util.Queue;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthOption;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthState;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.auth.NTCredentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.config.AuthSchemes;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.routing.RouteInfo;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.ProxyAuthenticationStrategy;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * Adds system proxy credentials only while selecting authentication for the current route's proxy.
+ */
+final class SystemProxyAuthenticationStrategy extends ProxyAuthenticationStrategy implements HttpRequestInterceptor {

Review Comment:
   **Nit:** Missing `@since` tag. `OriginScopedHeadersInterceptor` (added in the same 2.0.23 release cycle, same package) sets the precedent — even package-private classes carry `@since` here.
   
   ```suggestion
    * Adds system proxy credentials only while selecting authentication for the current route's proxy.
    *
    * @since 2.0.23
    */
   ```



##########
maven-resolver-transport-apache/src/main/java/org/eclipse/aether/transport/apache/SystemProxyAuthenticationStrategy.java:
##########
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eclipse.aether.transport.apache;
+
+import java.util.Map;
+import java.util.Queue;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthOption;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthState;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.auth.NTCredentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.config.AuthSchemes;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.routing.RouteInfo;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.ProxyAuthenticationStrategy;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * Adds system proxy credentials only while selecting authentication for the current route's proxy.
+ */
+final class SystemProxyAuthenticationStrategy extends ProxyAuthenticationStrategy implements HttpRequestInterceptor {
+    private static final String SYSTEM_PROXY = SystemProxyAuthenticationStrategy.class.getName() + ".proxy";
+
+    @Override
+    public void process(HttpRequest request, HttpContext context) {
+        HttpHost authenticatedProxy = (HttpHost) context.getAttribute(SYSTEM_PROXY);
+        RouteInfo route = HttpClientContext.adapt(context).getHttpRoute();
+        if (authenticatedProxy != null && route != null && !authenticatedProxy.equals(route.getProxyHost())) {
+            // HttpClient retains Basic proxy authentication across redirects, even when the proxy changes.
+            AuthState state = HttpClientContext.adapt(context).getProxyAuthState();
+            if (state != null) {
+                state.reset();
+            }
+            request.removeHeaders("Proxy-Authorization");
+            context.removeAttribute(SYSTEM_PROXY);
+        }
+    }
+
+    @Override
+    public Queue<AuthOption> select(
+            Map<String, Header> challenges, HttpHost authhost, HttpResponse response, HttpContext context)
+            throws MalformedChallengeException {
+        Queue<AuthOption> options = super.select(challenges, authhost, response, context);
+        if (!options.isEmpty()) {
+            return options;
+        }
+        RouteInfo route = HttpClientContext.adapt(context).getHttpRoute();
+        if (route == null || !authhost.equals(route.getProxyHost())) {
+            return options;
+        }
+        CredentialsProvider credentials = credentials(authhost, "http");
+        if (credentials == null) {
+            credentials = credentials(authhost, "https");
+        }
+        if (credentials == null) {
+            return options;
+        }
+        // A child context keeps proxy secrets out of server authentication, including after redirects.
+        HttpClientContext proxyContext = HttpClientContext.adapt(new BasicHttpContext(context));
+        proxyContext.setCredentialsProvider(credentials);
+        options = super.select(challenges, authhost, response, proxyContext);
+        if (!options.isEmpty()) {
+            context.setAttribute(SYSTEM_PROXY, authhost);
+        }
+        return options;
+    }
+
+    private static CredentialsProvider credentials(HttpHost proxy, String protocol) {
+        String prefix = protocol + ".proxy";
+        if (!proxy.getHostName().equalsIgnoreCase(System.getProperty(prefix + "Host"))) {
+            return null;
+        }
+        try {
+            if (proxy.getPort() != Integer.parseInt(System.getProperty(prefix + "Port"))) {
+                return null;
+            }
+        } catch (NumberFormatException e) {
+            return null;
+        }
+        String username = System.getProperty(prefix + "User");
+        if (username == null) {
+            return null;
+        }
+        String password = System.getProperty(prefix + "Password", "");
+        BasicCredentialsProvider credentials = new BasicCredentialsProvider();
+        credentials.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials(username, password));
+        credentials.setCredentials(
+                new AuthScope(proxy, AuthScope.ANY_REALM, AuthSchemes.NTLM),
+                new NTCredentials(username, password, null, System.getProperty("http.auth.ntlm.domain")));
+        return credentials;

Review Comment:
   **Informational:** `http.auth.ntlm.domain` is used regardless of `protocol`. Apache HC4 only defines this one property (no `https.auth.ntlm.domain` counterpart), so this is consistent with library conventions — but a short inline comment would save the next maintainer from wondering whether the hard-coded `"http."` prefix is a bug.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org