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 <[email protected]>
  • Loading branch information
ashishKhushiKumar committed Sep 24, 2024
1 parent e0dceb3 commit 0584db2
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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()) {
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 @@ -23,19 +23,27 @@
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;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.nio.charset.StandardCharsets;
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 +65,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
Expand Down
Loading

0 comments on commit 0584db2

Please sign in to comment.