Skip to content

Conversation

Copy link

Copilot AI commented Nov 4, 2025

Some HTTP proxy servers require the Proxy-Authorization header upfront rather than via 407 challenge-response flow, causing authentication failures.

Changes

  • ProtocolFactory.createHttpProxyRequest(): Set Proxy-Authorization header when credentials provided

    • Basic auth when username/password present: Basic <base64(user:pass)>
    • NTLM auth when domain/workstation also present: NTLM
    • UTF-8 encoding for credential bytes to ensure cross-platform consistency
  • Tests: Added coverage for Basic auth, NTLM auth, and no-credentials scenarios

Example

// Creates HTTP proxy request with Basic auth header
ProxyConnector connector = ProtocolFactory.createIoProxyConnector(
    socketConnector, address, proxyAddress, 
    "http", "1.0", "user", "password", null, null
);
// Header: "Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA=="

// Creates HTTP proxy request with NTLM auth header
ProxyConnector connector = ProtocolFactory.createIoProxyConnector(
    socketConnector, address, proxyAddress,
    "http", "1.0", "user", "password", "DOMAIN", "WORKSTATION"
);
// Header: "Proxy-Authorization: NTLM"

Backward compatible—only sets headers when credentials provided.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • localhost-quickfixj
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -Xmx2g -Djava.net.preferIPv4Stack=true --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-core/target/surefire/surefirebooter-20251104165534659_3.jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-core/target/surefire 2025-11-04T16-55-34_555-jvmRun1 surefire-20251104165534659_1tmp surefire_0-20251104165534659_2tmp (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -Xmx2g -Djava.net.preferIPv4Stack=true --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-core/target/surefire/surefirebooter-20251104170124673_3.jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-core/target/surefire 2025-11-04T17-01-24_581-jvmRun1 surefire-20251104170124673_1tmp surefire_0-20251104170124673_2tmp (dns block)
  • www.quickfixj.org
  • www.w3.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-base/target/surefire/surefirebooter-20251104165246502_8.jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-base/target/surefire 2025-11-04T16-52-39_498-jvmRun1 surefire-20251104165246502_6tmp surefire_1-20251104165246502_7tmp (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -Xmx2g -Djava.net.preferIPv4Stack=true --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-core/target/surefire/surefirebooter-20251104165534659_3.jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-core/target/surefire 2025-11-04T16-55-34_555-jvmRun1 surefire-20251104165534659_1tmp surefire_0-20251104165534659_2tmp (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java -Xmx2g -Djava.net.preferIPv4Stack=true --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-core/target/surefire/surefirebooter-20251104170124673_3.jar /home/REDACTED/work/quickfixj/quickfixj/quickfixj-core/target/surefire 2025-11-04T17-01-24_581-jvmRun1 surefire-20251104170124673_1tmp surefire_0-20251104170124673_2tmp (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Proxy-Authorization header solves Proxy 407</issue_title>
<issue_description>HTTP Proxy authentication was failing with a 407 error code. After an in-depth review, we discovered that the header sending was incorrect since the Proxy-Authorization key was missing. This pull request aims to solve this issue by configuring the appropriate header for HttpProxyRequest whenever credentials are provided. Note that the code supports both NTLM and Basic authentication methods. This code fixes our problem due to the correct authentication process from the headers set.

However, I personally cannot validate if this change is OK (also see quickfix-j#596) so it will probably take some time unless someone with more proxy experience can validate it for me. ;)
BTW, are you able to give me a hand with quickfix-j#596 ? Basically it is about testing QFJ against the current MINA 2.2 release.
Thanks and cheers
Chris

https://github.com/apache/mina/blob/2.2.X/mina-core/src/main/java/org/apache/mina/proxy/handlers/http/HttpSmartProxyHandler.java

When MINA's HTTP proxy handler does the handshake, the proxy server can respond with "407 - Proxy Authentication Required" status code which will make MINA's handler to automatically switch and choose HTTP auth method based on the response (no-auth, ntlm, digest and basic) and populate headers. However, I assume this might not be the case for all HTTP proxy servers and some some of them might require you to know the auth method in advance and you must ensure that headers are already populated. Hence the fix is required.

I think quickfix-j#631 looks reasonable, but we don't have HTTP tests yet so we don't know if this works. Also one thing about PR - the auth method is chosen based on properties provided, but I have a feeling that HTTP auth method should be configured explicitly.

somethign like bellow shoudl help

diff --git a/quickfixj-core/src/main/java/quickfix/mina/ProtocolFactory.java b/quickfixj-core/src/main/java/quickfix/mina/ProtocolFactory.java
index 13b88f0eec..cb3f69be58 100644
--- a/quickfixj-core/src/main/java/quickfix/mina/ProtocolFactory.java
+++ b/quickfixj-core/src/main/java/quickfix/mina/ProtocolFactory.java
@@ -21,7 +21,11 @@

import java.net.InetSocketAddress;
import java.net.SocketAddress;
+import java.util.Base64;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
+import java.util.Map;

import org.apache.mina.core.service.IoAcceptor;
@@ -150,17 +154,29 @@ private static ProxyRequest createHttpProxyRequest(InetSocketAddress address,
String proxyPassword,
String proxyDomain,
String proxyWorkstation) {

  •    HttpProxyRequest req = new HttpProxyRequest(address);
       HashMap<String, String> props = new HashMap<>();
    
  •    props.put(HttpProxyConstants.USER_PROPERTY, proxyUser);
    
  •    props.put(HttpProxyConstants.PWD_PROPERTY, proxyPassword);
    
  •    Map<String, List<String>> headers = new HashMap<>();
    
  •    boolean authenticationNTLM = false;
    
  •    if (proxyDomain != null && proxyWorkstation != null) {
           props.put(HttpProxyConstants.DOMAIN_PROPERTY, proxyDomain);
           props.put(HttpProxyConstants.WORKSTATION_PROPERTY, proxyWorkstation);
    
  •        authenticationNTLM = true;
    
  •    }
    
  •    if (proxyUser != null && proxyPassword != null) {
    
  •        props.put(HttpProxyConstants.USER_PROPERTY, proxyUser);
    
  •        props.put(HttpProxyConstants.PWD_PROPERTY, proxyPassword);
    
  •        String proxyCredentials = proxyUser + ":" + proxyPassword;
    
  •        String proxyCredentialsEncoded = Base64.getEncoder().encodeToString(proxyCredentials.getBytes());
    
  •        String proxyAuthorization = (authenticationNTLM ? "NTLM " : "Basic ") + proxyCredentialsEncoded;
    
  •        headers.put("Proxy-Authorization", Collections.singletonList(proxyAuthorization));
       }
    
  •    HttpProxyRequest req = new HttpProxyRequest(address);
       req.setProperties(props);
    
  •    if (proxyVersion != null && proxyVersion.equalsIgnoreCase("1.1")) {
    
  •    req.setHeaders(headers);
    
  •    if (proxyVersion != null && "1.1".equalsIgnoreCase(proxyVersion)) {
           req.setHttpVersion(HttpProxyConstants.HTTP_1_1);
       } else {
           req.setHttpVersion(HttpProxyConstants.HTTP_1_0);
    

</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits November 4, 2025 17:12
- Add support for Basic and NTLM authentication methods
- Set Proxy-Authorization header when credentials are provided
- Basic auth used when only user/password provided
- NTLM auth used when domain and workstation also provided
- Add comprehensive unit tests for all scenarios
- Fixes HTTP proxy 407 authentication errors

Co-authored-by: slachiewicz <6705942+slachiewicz@users.noreply.github.com>
- Ensures consistent encoding across platforms
- Prevents issues with non-ASCII characters in credentials

Co-authored-by: slachiewicz <6705942+slachiewicz@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix missing Proxy-Authorization header to resolve 407 error Add Proxy-Authorization header for HTTP proxy authentication Nov 4, 2025
Copilot AI requested a review from slachiewicz November 4, 2025 17:19
Copilot finished work on behalf of slachiewicz November 4, 2025 17:19
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

Successfully merging this pull request may close these issues.

Proxy-Authorization header solves Proxy 407

2 participants