Let's get started with a Microservice Architecture with Spring Cloud:
Proxy Authentication in Java
Last updated: January 29, 2026
1. Introduction
In this tutorial, we’ll see how to configure proxy authentication in Java. Many corporate environments require HTTP requests to pass through a proxy server, which often requires authentication credentials.
We’ll demonstrate how to configure proxy authentication using four popular approaches: the Java 11+ HttpClient, Apache HttpClient, Spring’s RestTemplate, and Spring’s WebClient.
2. Understanding Proxy Authentication
A proxy server intermediates requests between clients and resources. When a proxy requires authentication, clients must provide valid credentials in the Proxy-Authorization header after receiving an HTTP 407 response code before the proxy forwards requests to the target server.
While we don’t need to deal with headers directly, Java applications need to configure both the proxy server details (host and port) and credentials when making HTTP requests via an authenticated proxy.
2.1. Proxy Configuration Helper
Before checking the specific HTTP client implementations, let’s create a ProxyConfig class to encapsulate proxy settings:
public class ProxyConfig {
private String host;
private int port;
private String username;
private String password;
// default getters and setters and all-args constructor
// ...
}
Let’s also include a method to get a JVM authenticator:
public Authenticator authenticator() {
return new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
};
}
Then, a ProxySelector, which provides a mechanism to determine the proxy server to use during requests:
public ProxySelector proxySelector() {
return ProxySelector.of(new InetSocketAddress(host, port));
}
Finally, the Proxy definition:
public Proxy proxy() {
return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port));
}
We’ll use this to reduce boilerplate code when configuring our clients.
2.2. Accessing the Resource Server
In our tests, we need access to a resource server at localhost:8080, which requires authentication to a proxy at localhost:8079. So, this is the proxy configuration we’ll reuse:
ProxyConfig authProxyConfig = new ProxyConfig("localhost", 8079, "testuser", "testpass");
3. Using Java HttpClient
Java 11 introduced the HttpClient API as a modern replacement for the HttpURLConnection API. It provides support for proxy configuration and authentication.
3.1. Configuring the Client
We’ll use the HttpClient builder, using our ProxyConfig helper for configuration:
public static HttpClient createClient(ProxyConfig config) {
return HttpClient.newBuilder()
.proxy(config.proxySelector())
.authenticator(config.authenticator())
.build();
}
We use the proxySelector() method to configure the proxy address and the authenticator() method to provide credentials. The HttpClient automatically handles the authentication handshake when the proxy responds with a 407 status code.
3.2. Sending a Request
Once we have a configured client, we don’t need more configuration to make requests:
public static String sendRequest(HttpClient client, String url) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8080"))
.GET()
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
return response.body();
}
The client automatically uses the configured proxy and authentication for all requests.
3.3. Testing With MockServer
Let’s use MockServer to test that the proxy authentication works. We start by mocking a resource server:
@Test
void givenAuthenticatedProxy_whenSendRequest_thenSuccess() {
ClientAndServer resourceServer =
ClientAndServer.startClientAndServer(8080);
resourceServer.when(request().withMethod("GET")
.withPath("/secure"))
.respond(response().withStatusCode(200)
.withBody("Authenticated Response"));
// ...
}
Then, for mocking and configuring a proxy server, we’ll use the Configuration builder with the proxyAuthentication*() methods for defining the username and password:
Configuration config = Configuration.configuration()
.proxyAuthenticationUsername("testuser")
.proxyAuthenticationPassword("testpass");
proxyServer = ClientAndServer.startClientAndServer(config, 8079);
Finally, we use our ProxyConfig class to define proxy information, then create the client and send the request with the methods we created earlier:
ProxyConfig authProxyConfig = new ProxyConfig("localhost", 8079, "testuser", "testpass");
HttpClient client = createClient(authProxyConfig);
String response = sendRequest(client, "http://localhost:8080/secure");
assertEquals("Authenticated Response", response);
4. Using Apache HttpClient 5
Apache HttpClient 5 is a very common library with flexible proxy configuration.
4.1. Configuring the Client
We start with an HttpHost representing the proxy server:
public static CloseableHttpClient createClient(ProxyConfig config) {
HttpHost proxy = new HttpHost(config.getHost(), config.getPort());
// ...
}
For authenticated proxies, we need to configure a BasicCredentialsProvider and associate credentials with the proxy’s AuthScope:
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(proxy),
new UsernamePasswordCredentials(
config.getUsername(), config.getPassword().toCharArray()));
Note that in Apache HttpClient 5, the UsernamePasswordCredentials constructor now accepts a char array instead of a String password. This improves security because arrays can be explicitly cleared from memory after use.
After all this boilerplate, we can build our client by passing our proxy again in setProxy(). The client automatically provides credentials when the proxy requests authentication:
return HttpClients.custom()
.setProxy(proxy)
.setDefaultCredentialsProvider(credentialsProvider)
.build();
4.2. Sending Requests
We use the execute() method with a lambda response handler. This automatically handles resource cleanup, as the library ensures the response is properly closed:
public static String sendRequest(CloseableHttpClient client, String url) {
HttpGet request = new HttpGet(url);
return client.execute(
request, response -> EntityUtils.toString(response.getEntity()));
}
This is also simpler than the try-with-resources pattern used in the previous version.
5. Using Spring RestTemplate
Spring’s RestTemplate is a synchronous HTTP client commonly used in Spring applications.
5.1. Configuring the Client
We can configure it to work with proxies using the SimpleClientHttpRequestFactory:
public static RestTemplate createClient(ProxyConfig config) {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
// ...
}
With our ProxyConfig class, we use the proxy() method to get a configured Proxy instance, and the authenticator() for credentials:
requestFactory.setProxy(config.proxy());
Authenticator.setDefault(config.authenticator());
return new RestTemplate(requestFactory);
Note that Authenticator.setDefault() is JVM-wide. So, it won’t work for applications using multiple proxies.
5.2. Sending a Request
Sending requests with RestTemplate is simple:
public String sendRequest(RestTemplate restTemplate, String url) {
return restTemplate.getForObject(url, String.class);
}
Also, it handles all proxy and authentication details transparently.
6. Using Spring WebClient
Spring WebClient is the reactive alternative to RestTemplate, introduced in Spring 5. Most importantly, it provides better support for asynchronous operations.
6.1. Configuring the Client
WebClient uses the Reactor Netty HttpClient underneath:
public static WebClient createClient(ProxyConfig config) {
HttpClient httpClient = createHttpClient(config);
// ...
}
The Reactor Netty HttpClient provides a builder API for configuration. We use the proxy() method to set the proxy type, host, and port. Since authentication is required, we add a username and a password:
private static HttpClient createHttpClient(ProxyConfig config) {
return HttpClient.create().proxy(proxy -> proxy
.type(ProxyProvider.Proxy.HTTP)
.host(config.getHost())
.port(config.getPort())
.username(config.getUsername())
.password(u -> config.getPassword()));
}
The ReactorClientHttpConnector adapts this HttpClient for use with WebClient:
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
6.2. Sending a Request
With WebClient, we can make both synchronous and asynchronous requests:
public static String sendRequest(WebClient webClient, String url) {
return webClient.get()
.uri(url)
.retrieve()
.bodyToMono(String.class)
.block();
}
The retrieve() method starts the request, bodyToMono() extracts the response, and block() waits for the result. For asynchronous operations, we omit block() and use reactive operators.
7. Conclusion
In this article, we explored configuring proxy authentication in Java using four different approaches. The Java HttpClient provides a modern, built-in solution with a clean API. Apache HttpClient 5 provides fine-grained control. Spring’s RestTemplate integrates seamlessly with Spring applications. Spring’s WebClient provides reactive, non-blocking operations.
In the end, the choice depends on project requirements: use Java HttpClient for modern Java applications, Apache HttpClient 5 for maximum flexibility, RestTemplate for existing Spring-based projects, or WebClient for reactive Spring applications.
As always, the complete code examples are available over on GitHub.















