-
Bug
-
Resolution: Won't Fix
-
P4
-
None
-
17, 20, 21
A DESCRIPTION OF THE PROBLEM :
I am using the java.net.http.HttpClient to access a service that requires preemptive authentication.
I also configure an HTTP proxy with regular/challenge authentication.
Last important point is that I am doing an async request.
I found in the JDK code this code plus comment:
// Headers that are not generally restricted, and can therefore be set by users,
// but can in some contexts be overridden by the implementation.
// Currently, only contains "Authorization" which will
// be overridden, when an Authenticator is set on the HttpClient.
// Needs to be BiPred<String,String> to fit with general form of predicates
// used by caller.
public static final BiPredicate<String, String> CONTEXT_RESTRICTED(HttpClient client) {
return (k, v) -> !client.authenticator().isPresent() ||
(!k.equalsIgnoreCase("Authorization")
&& !k.equalsIgnoreCase("Proxy-Authorization"));
}
So from what I understand, as soon as you declare an Authenticator on the HttpClient (in my case to be used only for proxy authentication), then it is not possible to use preemptive authentication anymore, which is bad for my needs.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create an HTTPClient with a ProxySelector and an Authenticator that is only returning credentials if requestorType is proxy:
var httpClient = java.net.http.HttpClient.newBuilder()
.version(java.net.http.HttpClient.Version.HTTP_1_1)
.proxy(new ProxySelector() {
@Override
public List<Proxy> select(URI uri) {
// In my code, get the real list of proxies
return List.of();
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
}
})
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType() != RequestorType.PROXY) {
// We only handle proxy authentication here
return null;
}
// Simplified code
return new PasswordAuthentication(proxyUser, proxyPassword);
}
})
.build();
2. Send an async request with user defined Authorization headers:
var request = HttpRequest.newBuilder().uri(URI.create(url))
.setHeader("Authorization", "Basic " + credentialsEncoded);
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream());
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
User defined Authorization header is send to the server.
ACTUAL -
No Authorization header sent (checked with Wireshark).
CUSTOMER SUBMITTED WORKAROUND :
Could not find one so far.
FREQUENCY : always
I am using the java.net.http.HttpClient to access a service that requires preemptive authentication.
I also configure an HTTP proxy with regular/challenge authentication.
Last important point is that I am doing an async request.
I found in the JDK code this code plus comment:
// Headers that are not generally restricted, and can therefore be set by users,
// but can in some contexts be overridden by the implementation.
// Currently, only contains "Authorization" which will
// be overridden, when an Authenticator is set on the HttpClient.
// Needs to be BiPred<String,String> to fit with general form of predicates
// used by caller.
public static final BiPredicate<String, String> CONTEXT_RESTRICTED(HttpClient client) {
return (k, v) -> !client.authenticator().isPresent() ||
(!k.equalsIgnoreCase("Authorization")
&& !k.equalsIgnoreCase("Proxy-Authorization"));
}
So from what I understand, as soon as you declare an Authenticator on the HttpClient (in my case to be used only for proxy authentication), then it is not possible to use preemptive authentication anymore, which is bad for my needs.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create an HTTPClient with a ProxySelector and an Authenticator that is only returning credentials if requestorType is proxy:
var httpClient = java.net.http.HttpClient.newBuilder()
.version(java.net.http.HttpClient.Version.HTTP_1_1)
.proxy(new ProxySelector() {
@Override
public List<Proxy> select(URI uri) {
// In my code, get the real list of proxies
return List.of();
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
}
})
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType() != RequestorType.PROXY) {
// We only handle proxy authentication here
return null;
}
// Simplified code
return new PasswordAuthentication(proxyUser, proxyPassword);
}
})
.build();
2. Send an async request with user defined Authorization headers:
var request = HttpRequest.newBuilder().uri(URI.create(url))
.setHeader("Authorization", "Basic " + credentialsEncoded);
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream());
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
User defined Authorization header is send to the server.
ACTUAL -
No Authorization header sent (checked with Wireshark).
CUSTOMER SUBMITTED WORKAROUND :
Could not find one so far.
FREQUENCY : always
- relates to
-
JDK-8326949 Authorization header is removed when a proxy Authenticator is set on HttpClient
-
- Resolved
-