Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/main/java/com/auth0/AuthenticationController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.auth0;

import com.auth0.jwk.JwkProvider;
import com.auth0.net.client.Auth0HttpClient;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.Validate;

Expand Down Expand Up @@ -73,6 +74,7 @@ public static class Builder {
private final String clientSecret;
private String responseType;
private JwkProvider jwkProvider;
private Auth0HttpClient httpClient;
private Integer clockSkew;
private Integer authenticationMaxAge;
private boolean useLegacySameSiteCookie;
Expand Down Expand Up @@ -179,6 +181,39 @@ public Builder withJwkProvider(JwkProvider jwkProvider) {
return this;
}

/**
* Sets a custom {@link Auth0HttpClient} to use for all HTTP requests made by this library
* (token exchange, PAR, etc.). Use this to configure timeouts, proxies, or other HTTP settings.
*
* <p><strong>Note:</strong> When a custom {@code Auth0HttpClient} is provided, the
* {@link AuthenticationController#setLoggingEnabled(boolean)} and
* {@link AuthenticationController#doNotSendTelemetry()} settings will have no effect,
* as those are configured at the HTTP client level. You should configure logging and
* telemetry directly on the client instance before passing it here.</p>
*
* <pre>{@code
* Auth0HttpClient httpClient = DefaultHttpClient.newBuilder()
* .withConnectTimeout(10)
* .withReadTimeout(10)
* .telemetryEnabled(false)
* .withLogging(new LoggingOptions(LoggingOptions.LogLevel.BODY))
* .build();
*
* AuthenticationController controller = AuthenticationController
* .newBuilder(domain, clientId, clientSecret)
* .withHttpClient(httpClient)
* .build();
* }</pre>
*
* @param httpClient a configured {@link Auth0HttpClient} instance.
* @return this same builder instance.
*/
public Builder withHttpClient(Auth0HttpClient httpClient) {
Validate.notNull(httpClient, "httpClient must not be null");
this.httpClient = httpClient;
return this;
}

/**
* Sets the clock-skew or leeway value to use in the ID Token verification. The value must be in seconds.
* Defaults to 60 seconds.
Expand Down Expand Up @@ -267,6 +302,9 @@ public AuthenticationController build() throws UnsupportedOperationException {
if (jwkProvider != null) {
builder.withJwkProvider(jwkProvider);
}
if (httpClient != null) {
builder.withHttpClient(httpClient);
}

return new AuthenticationController(builder.build());
}
Expand Down
34 changes: 24 additions & 10 deletions src/main/java/com/auth0/RequestProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.UrlJwkProvider;
import com.auth0.net.client.Auth0HttpClient;
import com.auth0.net.client.DefaultHttpClient;
import com.auth0.utils.tokens.IdTokenVerifier;
import com.auth0.utils.tokens.SignatureVerifier;
Expand Down Expand Up @@ -50,6 +51,7 @@ class RequestProcessor {
private final String clientId;
private final String clientSecret;
private final JwkProvider jwkProvider;
private Auth0HttpClient httpClient;

private final Integer clockSkew;
private final Integer authenticationMaxAge;
Expand All @@ -71,6 +73,7 @@ static class Builder {
private final String clientSecret;

private JwkProvider jwkProvider;
private Auth0HttpClient httpClient;
private boolean useLegacySameSiteCookie = true;
private Integer clockSkew;
private Integer authenticationMaxAge;
Expand All @@ -93,6 +96,11 @@ Builder withJwkProvider(JwkProvider jwkProvider) {
return this;
}

Builder withHttpClient(Auth0HttpClient httpClient) {
this.httpClient = httpClient;
return this;
}

public Builder withClockSkew(Integer clockSkew) {
this.clockSkew = clockSkew;
return this;
Expand Down Expand Up @@ -125,20 +133,21 @@ Builder withInvitation(String invitation) {

RequestProcessor build() {
return new RequestProcessor(domainProvider, responseType, clientId, clientSecret,
jwkProvider, useLegacySameSiteCookie, clockSkew, authenticationMaxAge,
jwkProvider, httpClient, useLegacySameSiteCookie, clockSkew, authenticationMaxAge,
organization, invitation, cookiePath);
}
}

private RequestProcessor(DomainProvider domainProvider, String responseType, String clientId,
String clientSecret, JwkProvider jwkProvider,
String clientSecret, JwkProvider jwkProvider, Auth0HttpClient httpClient,
boolean useLegacySameSiteCookie, Integer clockSkew, Integer authenticationMaxAge,
String organization, String invitation, String cookiePath) {
this.domainProvider = domainProvider;
this.responseType = responseType;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.jwkProvider = jwkProvider;
this.httpClient = httpClient;
this.useLegacySameSiteCookie = useLegacySameSiteCookie;
this.clockSkew = clockSkew;
this.authenticationMaxAge = authenticationMaxAge;
Expand All @@ -156,18 +165,23 @@ void doNotSendTelemetry() {
}

AuthAPI createClientForDomain(String domain) {
DefaultHttpClient.Builder httpBuilder = DefaultHttpClient.newBuilder()
.telemetryEnabled(!telemetryDisabled);

if (loggingEnabled) {
httpBuilder.withLogging(new LoggingOptions(LoggingOptions.LogLevel.BODY));
}

return AuthAPI.newBuilder(domain, clientId, clientSecret)
.withHttpClient(httpBuilder.build())
.withHttpClient(getHttpClient())
.build();
}

private Auth0HttpClient getHttpClient() {
if (this.httpClient == null) {
DefaultHttpClient.Builder httpBuilder = DefaultHttpClient.newBuilder()
.telemetryEnabled(!telemetryDisabled);
if (loggingEnabled) {
httpBuilder.withLogging(new LoggingOptions(LoggingOptions.LogLevel.BODY));
}
this.httpClient = httpBuilder.build();
}
return this.httpClient;
}

/**
* Pre builds an Auth0 Authorize Url with the given redirect URI, state and nonce parameters.
*
Expand Down
44 changes: 44 additions & 0 deletions src/test/java/com/auth0/AuthenticationControllerTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.auth0;

import com.auth0.jwk.JwkProvider;
import com.auth0.net.client.Auth0HttpClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
Expand Down Expand Up @@ -31,6 +32,8 @@ public class AuthenticationControllerTest {
@Mock
private DomainResolver mockDomainResolver;
@Mock
private Auth0HttpClient mockHttpClient;
@Mock
private Tokens mockTokens;

private HttpServletRequest request;
Expand Down Expand Up @@ -82,6 +85,7 @@ public void shouldConfigureBuilderWithAllOptions() {
AuthenticationController controller = AuthenticationController.newBuilder(DOMAIN, CLIENT_ID, CLIENT_SECRET)
.withResponseType("id_token token")
.withJwkProvider(mockJwkProvider)
.withHttpClient(mockHttpClient)
.withClockSkew(120)
.withAuthenticationMaxAge(3600)
.withLegacySameSiteCookie(false)
Expand Down Expand Up @@ -131,6 +135,7 @@ public void shouldValidateNullParameters() {
assertThrows(NullPointerException.class, () -> builder.withDomain(null));
assertThrows(NullPointerException.class, () -> builder.withResponseType(null));
assertThrows(NullPointerException.class, () -> builder.withJwkProvider(null));
assertThrows(NullPointerException.class, () -> builder.withHttpClient(null));
assertThrows(NullPointerException.class, () -> builder.withClockSkew(null));
assertThrows(NullPointerException.class, () -> builder.withAuthenticationMaxAge(null));
assertThrows(NullPointerException.class, () -> builder.withOrganization(null));
Expand Down Expand Up @@ -421,4 +426,43 @@ public void shouldHandleImplicitGrantResponseType() {

assertThat(controller, is(notNullValue()));
}

// --- HttpClient Configuration Tests ---

@Test
public void shouldBuildWithCustomHttpClient() {
AuthenticationController controller = AuthenticationController.newBuilder(DOMAIN, CLIENT_ID, CLIENT_SECRET)
.withHttpClient(mockHttpClient)
.build();

assertThat(controller, is(notNullValue()));
assertThat(controller.getRequestProcessor(), is(notNullValue()));
}

@Test
public void shouldBuildWithCustomHttpClientAndJwkProvider() {
AuthenticationController controller = AuthenticationController.newBuilder(DOMAIN, CLIENT_ID, CLIENT_SECRET)
.withHttpClient(mockHttpClient)
.withJwkProvider(mockJwkProvider)
.build();

assertThat(controller, is(notNullValue()));
}

@Test
public void shouldBuildWithCustomHttpClientAndDomainResolver() {
AuthenticationController controller = AuthenticationController
.newBuilder(mockDomainResolver, CLIENT_ID, CLIENT_SECRET)
.withHttpClient(mockHttpClient)
.build();

assertThat(controller, is(notNullValue()));
}

@Test
public void shouldThrowExceptionWhenHttpClientIsNull() {
AuthenticationController.Builder builder = AuthenticationController.newBuilder(DOMAIN, CLIENT_ID, CLIENT_SECRET);

assertThrows(NullPointerException.class, () -> builder.withHttpClient(null));
}
}
Loading
Loading