diff --git a/examples/here-oauth-client-example/pom.xml b/examples/here-oauth-client-example/pom.xml
index 27c424c8..eb6f46b7 100644
--- a/examples/here-oauth-client-example/pom.xml
+++ b/examples/here-oauth-client-example/pom.xml
@@ -106,5 +106,9 @@
mockito-all
test
+
+ net.lightbody.bmp
+ browsermob-core
+
diff --git a/examples/here-oauth-client-example/src/main/java/com/here/account/oauth2/tutorial/HereAccessTokenProviderTutorial.java b/examples/here-oauth-client-example/src/main/java/com/here/account/oauth2/tutorial/HereAccessTokenProviderTutorial.java
index eb3601e8..e8521980 100644
--- a/examples/here-oauth-client-example/src/main/java/com/here/account/oauth2/tutorial/HereAccessTokenProviderTutorial.java
+++ b/examples/here-oauth-client-example/src/main/java/com/here/account/oauth2/tutorial/HereAccessTokenProviderTutorial.java
@@ -15,13 +15,15 @@
*/
package com.here.account.oauth2.tutorial;
-import java.util.List;
-import java.util.Map;
-
-import com.here.account.auth.OAuth2Authorizer;
-import com.here.account.http.HttpProvider;
-import com.here.account.http.HttpProvider.HttpRequest;
+import com.here.account.http.apache.ApacheHttpClientProvider;
import com.here.account.oauth2.HereAccessTokenProvider;
+import net.lightbody.bmp.BrowserMobProxy;
+import net.lightbody.bmp.BrowserMobProxyServer;
+import net.lightbody.bmp.proxy.auth.AuthType;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
/**
* A simple tutorial demonstrating how to get a HERE Access Token.
@@ -33,6 +35,8 @@ public class HereAccessTokenProviderTutorial {
public static void main(String[] argv) {
HereAccessTokenProviderTutorial t = new HereAccessTokenProviderTutorial(argv);
t.doGetAccessToken();
+ t.doGetAccessTokenViaProxy();
+ t.doGetAccessTokenViaProxyAndAuth();
}
private final Args args;
@@ -62,6 +66,87 @@ protected void doGetAccessToken() {
}
}
+
+ /**
+ * A simple method that builds a HereAccessTokenProvider via a proxy,
+ * gets one Access Token,
+ * and if successful outputs the first few characters of the valid token.
+ */
+ protected void doGetAccessTokenViaProxy() {
+ try {
+ // Creating custom httpClient for test purposes as real server will require SSL verification certificates
+ CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLContext(SSLContextBuilder.create().loadTrustMaterial((chain, authType) -> true).build())
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+ .build();
+ // Create a proxy
+ BrowserMobProxy proxy = new BrowserMobProxyServer();
+ // Start proxy
+ proxy.start(0);
+ try (
+ // use your provided System properties, ~/.here/credentials.ini, or credentials.properties file
+ HereAccessTokenProvider accessTokens = HereAccessTokenProvider.builder()
+ .setHttpProvider(ApacheHttpClientProvider.builder().setHttpClient(httpClient).build())
+ .setProxy("localhost", proxy.getPort())
+ .build()
+ ) {
+ // call accessTokens.getAccessToken(); every time one is needed, it will always be fresh
+ String accessToken = accessTokens.getAccessToken();
+ // use accessToken on a request...
+ useAccessToken(accessToken);
+ } catch (Exception e) {
+ trouble(e);
+ }
+ finally {
+ // Stop proxy
+ proxy.stop();
+ }
+ } catch (Exception e) {
+ trouble(e);
+ }
+ }
+
+ /**
+ * A simple method that builds a HereAccessTokenProvider via a proxy and Auth,
+ * gets one Access Token,
+ * and if successful outputs the first few characters of the valid token.
+ */
+ protected void doGetAccessTokenViaProxyAndAuth() {
+ try {
+ // Creating custom httpClient for test purposes as real server will require SSL verification certificates
+ CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLContext(SSLContextBuilder.create().loadTrustMaterial((chain, authType) -> true).build())
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+ .build();
+ // Create a proxy
+ BrowserMobProxy proxy = new BrowserMobProxyServer();
+ // Start proxy
+ proxy.start(0);
+ String proxyUsername = "yourUsername";
+ String proxyPassword = "yourPassword";
+ proxy.autoAuthorization("localhost:" + proxy.getPort(), proxyUsername, proxyPassword, AuthType.BASIC);
+ try (
+ // use your provided System properties, ~/.here/credentials.ini, or credentials.properties file
+ HereAccessTokenProvider accessTokens = HereAccessTokenProvider.builder()
+ .setHttpProvider(ApacheHttpClientProvider.builder().setHttpClient(httpClient).build())
+ .setProxy("localhost", proxy.getPort())
+ .setProxyAuthentication(proxyUsername, proxyPassword)
+ .build()
+ ) {
+ // call accessTokens.getAccessToken(); every time one is needed, it will always be fresh
+ String accessToken = accessTokens.getAccessToken();
+ // use accessToken on a request...
+ useAccessToken(accessToken);
+ } catch (Exception e) {
+ trouble(e);
+ } finally {
+ // Stop proxy
+ proxy.stop();
+ }
+ } catch (Exception e) {
+ trouble(e);
+ }
+ }
protected void useAccessToken(String accessToken) {
if (args.isVerbose()) {
diff --git a/here-oauth-client/pom.xml b/here-oauth-client/pom.xml
index ad514a84..5b8ae2f2 100644
--- a/here-oauth-client/pom.xml
+++ b/here-oauth-client/pom.xml
@@ -109,5 +109,11 @@
async-http-client
test
+
+ net.lightbody.bmp
+ browsermob-core
+ test
+
+
diff --git a/here-oauth-client/src/main/java/com/here/account/http/apache/ApacheHttpClientProvider.java b/here-oauth-client/src/main/java/com/here/account/http/apache/ApacheHttpClientProvider.java
index a486113d..7ac00ea5 100644
--- a/here-oauth-client/src/main/java/com/here/account/http/apache/ApacheHttpClientProvider.java
+++ b/here-oauth-client/src/main/java/com/here/account/http/apache/ApacheHttpClientProvider.java
@@ -25,7 +25,10 @@
import org.apache.http.Header;
import org.apache.http.HttpEntity;
+import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
@@ -40,8 +43,10 @@
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.entity.BasicHttpEntity;
+import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
@@ -92,6 +97,10 @@ public static class Builder {
private RequestConfig.Builder apacheConfigBuilder;
private CloseableHttpClient httpClient;
private boolean doCloseHttpClient = true;
+ private String proxyHost;
+ private int proxyPort;
+ private String proxyUsername;
+ private String proxyPassword;
private Builder() {
apacheConfigBuilder = RequestConfig.custom();
@@ -134,19 +143,37 @@ public Builder setConnectionTimeoutInMs(int connectionTimeoutInMs) {
return this;
}
+ public Builder setProxy(String proxyHost, int proxyPort) {
+ this.proxyHost = proxyHost;
+ this.proxyPort = proxyPort;
+ return this;
+ }
+
+ public Builder setProxyAuthentication(String proxyUsername, String proxyPassword) {
+ this.proxyUsername = proxyUsername;
+ this.proxyPassword = proxyPassword;
+ return this;
+ }
+
/**
* Build using builders, builders, and more builders.
*
* @return the built HttpProvider implementation for Apache httpclient.
*/
public HttpProvider build() {
-
- CloseableHttpClient client = this.httpClient != null ? this.httpClient :
- // uses PoolingHttpClientConnectionManager by default
- HttpClientBuilder.create().setDefaultRequestConfig(apacheConfigBuilder.build()).build();
-
+ HttpClientBuilder clientBuilder = HttpClientBuilder.create()
+ .setDefaultRequestConfig(apacheConfigBuilder.build());
+ if (null != proxyHost && proxyPort > 0) {
+ clientBuilder.setRoutePlanner(new DefaultProxyRoutePlanner(new HttpHost(proxyHost, proxyPort)));
+ if (null != proxyUsername && null != proxyPassword) {
+ BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+ credentialsProvider.setCredentials(new AuthScope(proxyHost, proxyPort),
+ new UsernamePasswordCredentials(proxyUsername, proxyPassword));
+ clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
+ }
+ }
+ CloseableHttpClient client = null != this.httpClient ? this.httpClient : clientBuilder.build();
return new ApacheHttpClientProvider(client, this.doCloseHttpClient);
-
}
}
diff --git a/here-oauth-client/src/main/java/com/here/account/oauth2/HereAccessTokenProvider.java b/here-oauth-client/src/main/java/com/here/account/oauth2/HereAccessTokenProvider.java
index e408d755..43108961 100644
--- a/here-oauth-client/src/main/java/com/here/account/oauth2/HereAccessTokenProvider.java
+++ b/here-oauth-client/src/main/java/com/here/account/oauth2/HereAccessTokenProvider.java
@@ -108,6 +108,10 @@ public static class Builder {
private boolean alwaysRequestNewToken = false;
private Serializer serializer;
private RetryPolicy retryPolicy;
+ private String proxyHost;
+ private int proxyPort;
+ private String proxyUsername;
+ private String proxyPassword;
private Builder() {
}
@@ -177,6 +181,29 @@ public Builder setRetryPolicy(RetryPolicy retryPolicy) {
return this;
}
+ /**
+ * Optionally set proxy endpoint configurations
+ * @param proxyHost proxy host
+ * @param proxyPort proxy port
+ * @return this Builder
+ */
+ public Builder setProxy(String proxyHost, int proxyPort) {
+ this.proxyHost = proxyHost;
+ this.proxyPort = proxyPort;
+ return this;
+ }
+
+ /**
+ * Optionally set proxy authentication configurations
+ * @param proxyUsername proxy username
+ * @param proxyPassword proxy password
+ * @return this Builder
+ */
+ public Builder setProxyAuthentication(String proxyUsername, String proxyPassword) {
+ this.proxyUsername = proxyUsername;
+ this.proxyPassword = proxyPassword;
+ return this;
+ }
/**
* Build using builders, builders, and more builders.
@@ -194,8 +221,15 @@ public HereAccessTokenProvider build() {
boolean doCloseHttpProvider = false;
if (null == httpProvider) {
+ ApacheHttpClientProvider.Builder apacheHttpClientProvider = ApacheHttpClientProvider.builder();
+ if (null != proxyHost && proxyPort > 0) {
+ apacheHttpClientProvider = apacheHttpClientProvider.setProxy(proxyHost, proxyPort);
+ if (null != proxyUsername && null != proxyPassword) {
+ apacheHttpClientProvider = apacheHttpClientProvider.setProxyAuthentication(proxyUsername, proxyPassword);
+ }
+ }
// uses PoolingHttpClientConnectionManager by default
- this.httpProvider = ApacheHttpClientProvider.builder().build();
+ this.httpProvider = apacheHttpClientProvider.build();
// because the httpProvider was not injected, we should close it
doCloseHttpProvider = true;
}
diff --git a/here-oauth-client/src/test/java/com/here/account/oauth2/HereAccessTokenProviderIT.java b/here-oauth-client/src/test/java/com/here/account/oauth2/HereAccessTokenProviderIT.java
index c8327da3..9774475f 100644
--- a/here-oauth-client/src/test/java/com/here/account/oauth2/HereAccessTokenProviderIT.java
+++ b/here-oauth-client/src/test/java/com/here/account/oauth2/HereAccessTokenProviderIT.java
@@ -23,8 +23,16 @@
import com.here.account.auth.provider.FromHereCredentialsIniFile;
import com.here.account.auth.provider.FromHereCredentialsIniStream;
import com.here.account.http.HttpProvider;
+import com.here.account.http.apache.ApacheHttpClientProvider;
import com.here.account.util.Clock;
import com.here.account.util.SettableSystemClock;
+import net.lightbody.bmp.BrowserMobProxy;
+import net.lightbody.bmp.BrowserMobProxyServer;
+import net.lightbody.bmp.proxy.auth.AuthType;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
@@ -34,8 +42,7 @@
import java.util.Map.Entry;
import java.util.Properties;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
/**
* @author kmccrack
@@ -57,6 +64,66 @@ public void test_builder_basic() throws IOException {
}
}
+ @Ignore // We don't want to create and run a server each time
+ @Test
+ public void test_builder_proxy() throws Exception {
+ // Creating custom httpClient for testing purposes as real server will require SSL verification certificates
+ CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLContext(SSLContextBuilder.create().loadTrustMaterial((chain, authType) -> true).build())
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+ .build();
+ // Create a proxy
+ BrowserMobProxy proxy = new BrowserMobProxyServer();
+ // Start proxy
+ proxy.start(0);
+ try (
+ HereAccessTokenProvider accessTokens = HereAccessTokenProvider.builder()
+ .setHttpProvider(ApacheHttpClientProvider.builder().setHttpClient(httpClient).build())
+ .setProxy("localhost", proxy.getPort())
+ .build()
+ ) {
+ String accessToken = accessTokens.getAccessToken();
+ assertNotNull("accessToken was null", accessToken);
+ assertFalse("accessToken was blank", accessToken.trim().isEmpty());
+ AccessTokenResponse accessTokenResponse = accessTokens.getAccessTokenResponse();
+ assertNotNull("accessTokenResponse was null", accessTokenResponse);
+ assertEquals("tokenType invalid", "bearer", accessTokenResponse.getTokenType());
+ }
+ proxy.stop();
+ }
+
+ @Ignore // We don't want to create and run a server each time
+ @Test
+ public void test_builder_proxy_and_auth() throws Exception {
+ // Creating custom httpClient for testing purposes as real server will require SSL verification certificates
+ CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLContext(SSLContextBuilder.create().loadTrustMaterial((chain, authType) -> true).build())
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+ .build();
+ // Create a proxy
+ BrowserMobProxy proxy = new BrowserMobProxyServer();
+ // Start proxy
+ proxy.start(0);
+ String proxyUsername = "yourUsername";
+ String proxyPassword = "yourPassword";
+ proxy.autoAuthorization("localhost:" + proxy.getPort(), proxyUsername, proxyPassword, AuthType.BASIC);
+ try (
+ HereAccessTokenProvider accessTokens = HereAccessTokenProvider.builder()
+ .setHttpProvider(ApacheHttpClientProvider.builder().setHttpClient(httpClient).build())
+ .setProxy("localhost", proxy.getPort())
+ .setProxyAuthentication(proxyUsername, proxyPassword)
+ .build()
+ ) {
+ String accessToken = accessTokens.getAccessToken();
+ assertNotNull("accessToken was null", accessToken);
+ assertFalse("accessToken was blank", accessToken.trim().isEmpty());
+ AccessTokenResponse accessTokenResponse = accessTokens.getAccessTokenResponse();
+ assertNotNull("accessTokenResponse was null", accessTokenResponse);
+ assertEquals("tokenType invalid", "bearer", accessTokenResponse.getTokenType());
+ }
+ proxy.stop();
+ }
+
private static final int ONE_HOUR_SKEW_MILLIS = 60 * 60 * 1000;
@Test
diff --git a/here-oauth-client/src/test/java/com/here/account/oauth2/HereAccessTokenProviderTest.java b/here-oauth-client/src/test/java/com/here/account/oauth2/HereAccessTokenProviderTest.java
index 4b9aaeea..5344f69c 100644
--- a/here-oauth-client/src/test/java/com/here/account/oauth2/HereAccessTokenProviderTest.java
+++ b/here-oauth-client/src/test/java/com/here/account/oauth2/HereAccessTokenProviderTest.java
@@ -15,6 +15,8 @@
*/
package com.here.account.oauth2;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
@@ -265,6 +267,60 @@ public void test_HereAccessTokenProvider_defaultHttpProvider() throws IOExceptio
}
}
+ @Test
+ public void test_HereAccessTokenProvider_withProxy() throws IOException, HttpException {
+ HttpProvider mockHttpProvider = Mockito.mock(HttpProvider.class);
+ HttpProvider.HttpResponse mockHttpResponse = Mockito.mock(HttpProvider.HttpResponse.class);
+ String responseBody = HereAccountTest.getResponseBody(expectedAccessToken, expectedScope);
+ byte[] bytes = responseBody.getBytes(StandardCharsets.UTF_8);
+ Mockito.when(mockHttpResponse.getStatusCode()).thenReturn(200);
+ Mockito.when(mockHttpResponse.getResponseBody()).thenReturn(new ByteArrayInputStream(bytes));
+ Mockito.when(mockHttpProvider.execute(Mockito.any(HttpProvider.HttpRequest.class)))
+ .thenReturn(mockHttpResponse);
+ try (
+ HereAccessTokenProvider hereAccessTokenProvider = HereAccessTokenProvider.builder()
+ .setHttpProvider(mockHttpProvider)
+ .setClientAuthorizationRequestProvider(clientAuthorizationRequestProvider)
+ .setProxy("localhost", 8000)
+ .build()
+ ) {
+ AccessTokenResponse accessTokenResponse = hereAccessTokenProvider.getAccessTokenResponse();
+ assertNotNull("accessTokenResponse was null", accessTokenResponse);
+ String accessToken = accessTokenResponse.getAccessToken();
+ assertEquals("expected accessToken " + expectedAccessToken + ", actual " + accessToken,
+ expectedAccessToken, accessToken);
+ String scope = accessTokenResponse.getScope();
+ assertEquals("expected scope " + expectedScope + ", actual " + scope, expectedScope, scope);
+ }
+ }
+ @Test
+ public void test_HereAccessTokenProvider_withProxyAuthentication() throws IOException, HttpException {
+ HttpProvider mockHttpProvider = Mockito.mock(HttpProvider.class);
+ HttpProvider.HttpResponse mockHttpResponse = Mockito.mock(HttpProvider.HttpResponse.class);
+ String responseBody = HereAccountTest.getResponseBody(expectedAccessToken, expectedScope);
+ byte[] bytes = responseBody.getBytes(StandardCharsets.UTF_8);
+ Mockito.when(mockHttpResponse.getStatusCode()).thenReturn(200);
+ Mockito.when(mockHttpResponse.getResponseBody()).thenReturn(new ByteArrayInputStream(bytes));
+ Mockito.when(mockHttpProvider.execute(Mockito.any(HttpProvider.HttpRequest.class)))
+ .thenReturn(mockHttpResponse);
+ try (
+ HereAccessTokenProvider hereAccessTokenProvider
+ = HereAccessTokenProvider.builder()
+ .setHttpProvider(mockHttpProvider)
+ .setClientAuthorizationRequestProvider(clientAuthorizationRequestProvider)
+ .setProxy("localhost", 8000)
+ .setProxyAuthentication("myUsername", "myPassword")
+ .build()
+ ) {
+ AccessTokenResponse accessTokenResponse = hereAccessTokenProvider.getAccessTokenResponse();
+ assertNotNull("accessTokenResponse was null", accessTokenResponse);
+ String accessToken = accessTokenResponse.getAccessToken();
+ assertEquals("expected accessToken " + expectedAccessToken + ", actual " + accessToken,
+ expectedAccessToken, accessToken);
+ String scope = accessTokenResponse.getScope();
+ assertEquals("expected scope " + expectedScope + ", actual " + scope, expectedScope, scope);
+ }
+ }
}
diff --git a/here-oauth-client/src/test/java/com/here/account/oauth2/SignInWithClientCredentialsIT.java b/here-oauth-client/src/test/java/com/here/account/oauth2/SignInWithClientCredentialsIT.java
index 1b21d0fd..e09fdd50 100644
--- a/here-oauth-client/src/test/java/com/here/account/oauth2/SignInWithClientCredentialsIT.java
+++ b/here-oauth-client/src/test/java/com/here/account/oauth2/SignInWithClientCredentialsIT.java
@@ -149,7 +149,7 @@ public void test_signIn_wrongClock() throws Exception {
String error = errorResponse.getError();
String expectedError = "invalid_request";
assertTrue("expected error " + expectedError + ", actual " + error, expectedError.equals(error));
- String expectedErrorDescriptionContains = "timestamp";
+ String expectedErrorDescriptionContains = "offset";
String errorDescription = errorResponse.getErrorDescription();
assertTrue("expected error_description to contain " + errorDescription + ", actual " + errorDescription,
null != errorDescription && errorDescription.contains(expectedErrorDescriptionContains));
diff --git a/pom.xml b/pom.xml
index 318a1c45..beb33826 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,7 @@
4.13.1
1.10.19
1.8.17
+ 2.1.5
@@ -138,6 +139,11 @@
${ning.version}
test
+
+ net.lightbody.bmp
+ browsermob-core
+ ${browsermob.version}
+