Skip to content

Commit

Permalink
AAA-24174 Support proxy for HereAccessTokenProvider
Browse files Browse the repository at this point in the history
Signed-off-by: Author Name <authoremail@example.com>
  • Loading branch information
ashishKhushiKumar committed Sep 23, 2024
1 parent e0dceb3 commit f1e2c02
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@
*/
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.oauth2.HereAccessTokenProvider;
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.proxy.auth.AuthType;

/**
* A simple tutorial demonstrating how to get a HERE Access Token.
Expand All @@ -33,6 +30,7 @@ public class HereAccessTokenProviderTutorial {
public static void main(String[] argv) {
HereAccessTokenProviderTutorial t = new HereAccessTokenProviderTutorial(argv);
t.doGetAccessToken();
t.doGetAccessTokenViaProxy();
}

private final Args args;
Expand Down Expand Up @@ -62,6 +60,60 @@ 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() {
BrowserMobProxy proxy = new BrowserMobProxyServer(); // Replace with you own proxy
proxy.start(0);
try (
// use your provided System properties, ~/.here/credentials.ini, or credentials.properties file
HereAccessTokenProvider accessTokens = HereAccessTokenProvider.builder()
.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 {
proxy.stop();
}
}

/**
* 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() {
BrowserMobProxy proxy = new BrowserMobProxyServer(); // Replace with you own proxy
proxy.start(0);
String proxyUsername = "yourUsername"; // Replace with your actual username
String proxyPassword = "yourPassword"; // Replace with your actual password
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()
.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 {
proxy.stop();
}
}

protected void useAccessToken(String accessToken) {
if (args.isVerbose()) {
Expand Down
6 changes: 6 additions & 0 deletions here-oauth-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,11 @@
<artifactId>async-http-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.lightbody.bmp</groupId>
<artifactId>browsermob-core</artifactId>
<version>2.1.5</version>
</dependency>

</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
}
Expand Down Expand Up @@ -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.
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import com.here.account.http.HttpProvider;
import com.here.account.util.Clock;
import com.here.account.util.SettableSystemClock;
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
Expand All @@ -34,8 +36,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
Expand All @@ -57,6 +58,25 @@ public void test_builder_basic() throws IOException {
}
}

@Test
public void test_builder_proxy() throws Exception {
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.start(0);
try (
HereAccessTokenProvider accessTokens = HereAccessTokenProvider.builder()
.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();
}

private static final int ONE_HOUR_SKEW_MILLIS = 60 * 60 * 1000;

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@
<version>${ning.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.lightbody.bmp</groupId>
<artifactId>browsermob-core</artifactId>
<version>2.1.5</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down

0 comments on commit f1e2c02

Please sign in to comment.