Auth library updated to support access token reuse and IAM role
This commit is contained in:
parent
542c2a9b2a
commit
f737a56175
|
@ -108,6 +108,12 @@
|
|||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.9</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-sts -->
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-sts</artifactId>
|
||||
<version>1.11.236</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -43,10 +43,13 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
{{/fullJavaUtil}}
|
||||
|
||||
import com.amazon.SellingPartnerAPIAA.AWSSigV4Signer;
|
||||
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationSigner;
|
||||
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationCredentials;
|
||||
import com.amazon.SellingPartnerAPIAA.AWSAuthenticationCredentials;
|
||||
import com.amazon.SellingPartnerAPIAA.AWSAuthenticationCredentialsProvider;
|
||||
import com.amazon.SellingPartnerAPIAA.AWSSigV4Signer;
|
||||
import com.amazon.SellingPartnerAPIAA.LWAAccessTokenCache;
|
||||
import com.amazon.SellingPartnerAPIAA.LWAAccessTokenCacheImpl;
|
||||
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationCredentials;
|
||||
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationSigner;
|
||||
|
||||
{{#operations}}
|
||||
public class {{classname}} {
|
||||
|
@ -275,6 +278,9 @@ public class {{classname}} {
|
|||
private AWSAuthenticationCredentials awsAuthenticationCredentials;
|
||||
private LWAAuthorizationCredentials lwaAuthorizationCredentials;
|
||||
private String endpoint;
|
||||
private LWAAccessTokenCache lwaAccessTokenCache;
|
||||
private Boolean disableAccessTokenCache = false;
|
||||
private AWSAuthenticationCredentialsProvider awsAuthenticationCredentialsProvider;
|
||||
|
||||
public Builder awsAuthenticationCredentials(AWSAuthenticationCredentials awsAuthenticationCredentials) {
|
||||
this.awsAuthenticationCredentials = awsAuthenticationCredentials;
|
||||
|
@ -291,6 +297,22 @@ public class {{classname}} {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder lwaAccessTokenCache(LWAAccessTokenCache lwaAccessTokenCache) {
|
||||
this.lwaAccessTokenCache = lwaAccessTokenCache;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder disableAccessTokenCache() {
|
||||
this.disableAccessTokenCache = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder awsAuthenticationCredentialsProvider(AWSAuthenticationCredentialsProvider awsAuthenticationCredentialsProvider) {
|
||||
this.awsAuthenticationCredentialsProvider = awsAuthenticationCredentialsProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public {{classname}} build() {
|
||||
if (awsAuthenticationCredentials == null) {
|
||||
throw new RuntimeException("AWSAuthenticationCredentials not set");
|
||||
|
@ -304,8 +326,24 @@ public class {{classname}} {
|
|||
throw new RuntimeException("Endpoint not set");
|
||||
}
|
||||
|
||||
AWSSigV4Signer awsSigV4Signer = new AWSSigV4Signer(awsAuthenticationCredentials);
|
||||
LWAAuthorizationSigner lwaAuthorizationSigner = new LWAAuthorizationSigner(lwaAuthorizationCredentials);
|
||||
AWSSigV4Signer awsSigV4Signer;
|
||||
if ( awsAuthenticationCredentialsProvider == null) {
|
||||
awsSigV4Signer = new AWSSigV4Signer(awsAuthenticationCredentials);
|
||||
}
|
||||
else {
|
||||
awsSigV4Signer = new AWSSigV4Signer(awsAuthenticationCredentials,awsAuthenticationCredentialsProvider);
|
||||
}
|
||||
|
||||
LWAAuthorizationSigner lwaAuthorizationSigner = null;
|
||||
if (disableAccessTokenCache) {
|
||||
lwaAuthorizationSigner = new LWAAuthorizationSigner(lwaAuthorizationCredentials);
|
||||
}
|
||||
else {
|
||||
if (lwaAccessTokenCache == null) {
|
||||
lwaAccessTokenCache = new LWAAccessTokenCacheImpl();
|
||||
}
|
||||
lwaAuthorizationSigner = new LWAAuthorizationSigner(lwaAuthorizationCredentials,lwaAccessTokenCache);
|
||||
}
|
||||
|
||||
return new {{classname}}(new ApiClient()
|
||||
.setAWSSigV4Signer(awsSigV4Signer)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package com.amazon.SellingPartnerAPIAA;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* AWSAuthenticationCredentialsProvider
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class AWSAuthenticationCredentialsProvider {
|
||||
/**
|
||||
* AWS IAM Role ARN
|
||||
*/
|
||||
private String roleArn;
|
||||
|
||||
/**
|
||||
* AWS IAM Role Session Name
|
||||
*/
|
||||
private String roleSessionName;
|
||||
|
||||
|
||||
}
|
|
@ -3,11 +3,15 @@ package com.amazon.SellingPartnerAPIAA;
|
|||
import com.amazonaws.SignableRequest;
|
||||
import com.amazonaws.auth.AWS4Signer;
|
||||
import com.amazonaws.auth.AWSCredentials;
|
||||
import com.amazonaws.auth.AWSCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.squareup.okhttp.Request;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
|
||||
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
|
||||
/**
|
||||
* AWS Signature Version 4 Signer
|
||||
|
@ -21,6 +25,10 @@ public class AWSSigV4Signer {
|
|||
|
||||
private AWSCredentials awsCredentials;
|
||||
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private AWSCredentialsProvider awsCredentialsProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param awsAuthenticationCredentials AWS Developer Account Credentials
|
||||
|
@ -33,6 +41,26 @@ public class AWSSigV4Signer {
|
|||
awsAuthenticationCredentials.getSecretKey());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param awsAuthenticationCredentials and awsAuthenticationCredentialsProvider AWS Developer Account Credentials
|
||||
*/
|
||||
public AWSSigV4Signer(AWSAuthenticationCredentials awsAuthenticationCredentials,
|
||||
AWSAuthenticationCredentialsProvider awsAuthenticationCredentialsProvider) {
|
||||
aws4Signer = new AWS4Signer();
|
||||
aws4Signer.setServiceName(SERVICE_NAME);
|
||||
aws4Signer.setRegionName(awsAuthenticationCredentials.getRegion());
|
||||
BasicAWSCredentials awsBasicCredentials = new BasicAWSCredentials(awsAuthenticationCredentials.getAccessKeyId(),
|
||||
awsAuthenticationCredentials.getSecretKey());
|
||||
awsCredentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(
|
||||
awsAuthenticationCredentialsProvider.getRoleArn(),
|
||||
awsAuthenticationCredentialsProvider.getRoleSessionName())
|
||||
.withStsClient(AWSSecurityTokenServiceClientBuilder.standard()
|
||||
.withRegion(awsAuthenticationCredentials.getRegion())
|
||||
.withCredentials(new AWSStaticCredentialsProvider(awsBasicCredentials)).build())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a Request with AWS Signature Version 4
|
||||
*
|
||||
|
@ -41,8 +69,11 @@ public class AWSSigV4Signer {
|
|||
*/
|
||||
public Request sign(Request originalRequest) {
|
||||
SignableRequest<Request> signableRequest = new SignableRequestImpl(originalRequest);
|
||||
if (awsCredentialsProvider != null) {
|
||||
aws4Signer.sign(signableRequest, awsCredentialsProvider.getCredentials());
|
||||
} else {
|
||||
aws4Signer.sign(signableRequest, awsCredentials);
|
||||
|
||||
}
|
||||
return (Request) signableRequest.getOriginalRequestObject();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package com.amazon.SellingPartnerAPIAA;
|
||||
|
||||
public interface LWAAccessTokenCache {
|
||||
String get(Object key);
|
||||
void put(Object key, String accessToken, long tokenTTLInSeconds);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.amazon.SellingPartnerAPIAA;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class LWAAccessTokenCacheImpl implements LWAAccessTokenCache {
|
||||
//in milliseconds; to avoid returning a token that would expire before or while a request is made
|
||||
private long expiryAdjustment = 60 * 1000;
|
||||
private static final long SECOND_TO_MILLIS = 1000;
|
||||
private ConcurrentHashMap<Object, Object> accessTokenHashMap =
|
||||
new ConcurrentHashMap<Object, Object>();
|
||||
@Override
|
||||
public void put(Object oLWAAccessTokenRequestMeta, String accessToken, long tokenTTLInSeconds) {
|
||||
LWAAccessTokenCacheItem accessTokenCacheItem = new LWAAccessTokenCacheItem();
|
||||
long insertTime = System.currentTimeMillis();
|
||||
long accessTokenExpiresValueMillis = (tokenTTLInSeconds * SECOND_TO_MILLIS) + insertTime;
|
||||
accessTokenCacheItem.setAccessToken(accessToken);
|
||||
accessTokenCacheItem.setAccessTokenExpiredTime(accessTokenExpiresValueMillis);
|
||||
accessTokenHashMap.put(oLWAAccessTokenRequestMeta, accessTokenCacheItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(Object oLWAAccessTokenRequestMeta) {
|
||||
Object accessTokenValue = accessTokenHashMap.get(oLWAAccessTokenRequestMeta);
|
||||
if (accessTokenValue != null) {
|
||||
LWAAccessTokenCacheItem accessTokenData =
|
||||
(LWAAccessTokenCacheItem) accessTokenValue;
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long accessTokenExpiredTime = accessTokenData.getAccessTokenExpiredTime() - expiryAdjustment;
|
||||
if (currentTime < accessTokenExpiredTime) {
|
||||
return accessTokenData.getAccessToken();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.amazon.SellingPartnerAPIAA;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
class LWAAccessTokenCacheItem {
|
||||
|
||||
private String accessToken;
|
||||
private long accessTokenExpiredTime;
|
||||
|
||||
}
|
|
@ -10,7 +10,6 @@ import lombok.Setter;
|
|||
*/
|
||||
public class LWAAuthorizationSigner {
|
||||
private static final String SIGNED_ACCESS_TOKEN_HEADER_NAME = "x-amz-access-token";
|
||||
private final String tokenRequestGrantType;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
|
@ -18,14 +17,8 @@ public class LWAAuthorizationSigner {
|
|||
|
||||
private LWAAccessTokenRequestMeta lwaAccessTokenRequestMeta;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lwaAuthorizationCredentials LWA Authorization Credentials for token exchange
|
||||
*/
|
||||
public LWAAuthorizationSigner(LWAAuthorizationCredentials lwaAuthorizationCredentials) {
|
||||
|
||||
lwaClient = new LWAClient(lwaAuthorizationCredentials.getEndpoint());
|
||||
|
||||
private void buildLWAAccessTokenRequestMeta(LWAAuthorizationCredentials lwaAuthorizationCredentials) {
|
||||
String tokenRequestGrantType;
|
||||
if (!lwaAuthorizationCredentials.getScopes().isEmpty()) {
|
||||
tokenRequestGrantType = "client_credentials";
|
||||
} else {
|
||||
|
@ -38,6 +31,33 @@ public class LWAAuthorizationSigner {
|
|||
.refreshToken(lwaAuthorizationCredentials.getRefreshToken())
|
||||
.grantType(tokenRequestGrantType).scopes(lwaAuthorizationCredentials.getScopes())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lwaAuthorizationCredentials LWA Authorization Credentials for token exchange
|
||||
*/
|
||||
public LWAAuthorizationSigner(LWAAuthorizationCredentials lwaAuthorizationCredentials) {
|
||||
|
||||
lwaClient = new LWAClient(lwaAuthorizationCredentials.getEndpoint());
|
||||
|
||||
buildLWAAccessTokenRequestMeta(lwaAuthorizationCredentials);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Overloaded Constructor @param lwaAuthorizationCredentials LWA Authorization Credentials for token exchange
|
||||
* and LWAAccessTokenCache
|
||||
*/
|
||||
public LWAAuthorizationSigner(LWAAuthorizationCredentials lwaAuthorizationCredentials,
|
||||
LWAAccessTokenCache lwaAccessTokenCache) {
|
||||
|
||||
lwaClient = new LWAClient(lwaAuthorizationCredentials.getEndpoint());
|
||||
lwaClient.setLWAAccessTokenCache(lwaAccessTokenCache);
|
||||
|
||||
buildLWAAccessTokenRequestMeta(lwaAuthorizationCredentials);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,13 +16,19 @@ import java.io.IOException;
|
|||
|
||||
class LWAClient {
|
||||
private static final String ACCESS_TOKEN_KEY = "access_token";
|
||||
private static final String ACCESS_TOKEN_EXPIRES_IN = "expires_in";
|
||||
private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");
|
||||
|
||||
@Getter
|
||||
private String endpoint;
|
||||
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private OkHttpClient okHttpClient;
|
||||
private LWAAccessTokenCache lwaAccessTokenCache;
|
||||
|
||||
/** Sets cache to store access token until token is expired */
|
||||
public void setLWAAccessTokenCache(LWAAccessTokenCache tokenCache) {
|
||||
this.lwaAccessTokenCache = tokenCache;
|
||||
}
|
||||
|
||||
LWAClient(String endpoint) {
|
||||
okHttpClient = new OkHttpClient();
|
||||
|
@ -30,12 +36,25 @@ class LWAClient {
|
|||
}
|
||||
|
||||
String getAccessToken(LWAAccessTokenRequestMeta lwaAccessTokenRequestMeta) {
|
||||
RequestBody requestBody = RequestBody.create(JSON_MEDIA_TYPE,
|
||||
new Gson().toJson(lwaAccessTokenRequestMeta));
|
||||
Request accessTokenRequest = new Request.Builder()
|
||||
.url(endpoint)
|
||||
.post(requestBody)
|
||||
.build();
|
||||
if (lwaAccessTokenCache != null) {
|
||||
return getAccessTokenFromCache(lwaAccessTokenRequestMeta);
|
||||
} else {
|
||||
return getAccessTokenFromEndpoint(lwaAccessTokenRequestMeta);
|
||||
}
|
||||
}
|
||||
|
||||
String getAccessTokenFromCache(LWAAccessTokenRequestMeta lwaAccessTokenRequestMeta) {
|
||||
String accessTokenCacheData = (String) lwaAccessTokenCache.get(lwaAccessTokenRequestMeta);
|
||||
if (accessTokenCacheData != null) {
|
||||
return accessTokenCacheData;
|
||||
} else {
|
||||
return getAccessTokenFromEndpoint(lwaAccessTokenRequestMeta);
|
||||
}
|
||||
}
|
||||
|
||||
String getAccessTokenFromEndpoint(LWAAccessTokenRequestMeta lwaAccessTokenRequestMeta) {
|
||||
RequestBody requestBody = RequestBody.create(JSON_MEDIA_TYPE, new Gson().toJson(lwaAccessTokenRequestMeta));
|
||||
Request accessTokenRequest = new Request.Builder().url(endpoint).post(requestBody).build();
|
||||
|
||||
String accessToken;
|
||||
try {
|
||||
|
@ -44,15 +63,16 @@ class LWAClient {
|
|||
throw new IOException("Unsuccessful LWA token exchange");
|
||||
}
|
||||
|
||||
JsonObject responseJson = new JsonParser()
|
||||
.parse(response.body().string())
|
||||
.getAsJsonObject();
|
||||
JsonObject responseJson = new JsonParser().parse(response.body().string()).getAsJsonObject();
|
||||
|
||||
accessToken = responseJson.get(ACCESS_TOKEN_KEY).getAsString();
|
||||
if (lwaAccessTokenCache != null) {
|
||||
long timeToTokenexpiry = responseJson.get(ACCESS_TOKEN_EXPIRES_IN).getAsLong();
|
||||
lwaAccessTokenCache.put(lwaAccessTokenRequestMeta, accessToken, timeToTokenexpiry);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error getting LWA Access Token", e);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,16 @@ package com.amazon.SellingPartnerAPIAA;
|
|||
import com.amazonaws.SignableRequest;
|
||||
import com.amazonaws.auth.AWS4Signer;
|
||||
import com.amazonaws.auth.AWSCredentials;
|
||||
import com.amazonaws.auth.AWSCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
|
||||
import com.squareup.okhttp.Request;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -21,11 +25,18 @@ public class AWSSigV4SignerTest {
|
|||
private static final String TEST_ACCESS_KEY_ID = "aKey";
|
||||
private static final String TEST_SECRET_KEY = "sKey";
|
||||
private static final String TEST_REGION = "us-east";
|
||||
private static final String TEST_ROLE_ARN = "arnrole";
|
||||
private static final String TEST_ROLESESSION_NAME = "test";
|
||||
|
||||
@Mock
|
||||
private AWS4Signer mockAWS4Signer;
|
||||
@Mock
|
||||
private AWSCredentialsProvider mockAWSCredentialsProvider;
|
||||
@Mock
|
||||
private AWSCredentials mockAWSCredentials;
|
||||
|
||||
private AWSSigV4Signer underTest;
|
||||
private AWSSigV4Signer underTestCredentialsProvider;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
|
@ -80,4 +91,36 @@ public class AWSSigV4SignerTest {
|
|||
|
||||
assertEquals(((Request)actualSignableRequest.getOriginalRequestObject()).url(), actualSignedRequest.url());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnSignedRequestWithCredentialProvider() {
|
||||
ArgumentCaptor<SignableRequest> signableRequestArgumentCaptor = ArgumentCaptor.forClass(SignableRequest.class);
|
||||
|
||||
Mockito.when(mockAWSCredentialsProvider.getCredentials()).thenReturn(mockAWSCredentials);
|
||||
|
||||
underTestCredentialsProvider = new AWSSigV4Signer(AWSAuthenticationCredentials.builder()
|
||||
.accessKeyId(TEST_ACCESS_KEY_ID)
|
||||
.secretKey(TEST_SECRET_KEY)
|
||||
.region(TEST_REGION)
|
||||
.build(), AWSAuthenticationCredentialsProvider.builder()
|
||||
.roleArn(TEST_ROLE_ARN)
|
||||
.roleSessionName(TEST_ROLESESSION_NAME)
|
||||
.build()
|
||||
);
|
||||
underTestCredentialsProvider.setAws4Signer(mockAWS4Signer);
|
||||
underTestCredentialsProvider.setAwsCredentialsProvider(mockAWSCredentialsProvider);
|
||||
|
||||
Request actualSignedRequest = underTestCredentialsProvider.sign(new Request.Builder()
|
||||
.url("http://api.amazon.com")
|
||||
.build());
|
||||
|
||||
verify(mockAWS4Signer)
|
||||
.sign(signableRequestArgumentCaptor.capture(), any(AWSCredentials.class));
|
||||
|
||||
SignableRequest actualSignableRequest = signableRequestArgumentCaptor.getValue();
|
||||
|
||||
assertEquals(((Request)actualSignableRequest.getOriginalRequestObject()).url(), actualSignedRequest.url());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,25 +1,38 @@
|
|||
package com.amazon.SellingPartnerAPIAA;
|
||||
|
||||
import com.squareup.okhttp.Call;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Protocol;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
import com.squareup.okhttp.ResponseBody;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_MIGRATION_API;
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_NOTIFICATIONS_API;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_NOTIFICATIONS_API;
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_MIGRATION_API;
|
||||
|
||||
public class LWAAuthorizationSignerTest {
|
||||
private static final String TEST_REFRESH_TOKEN = "rToken";
|
||||
private static final String TEST_CLIENT_SECRET = "cSecret";
|
||||
|
@ -29,12 +42,19 @@ public class LWAAuthorizationSignerTest {
|
|||
private static final String TEST_SCOPE_2 = SCOPE_MIGRATION_API;
|
||||
private static final String SELLER_TYPE_SELLER = "seller";
|
||||
private static final String SELLER_TYPE_SELLERLESS = "sellerless";
|
||||
private static final MediaType EXPECTED_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");
|
||||
|
||||
|
||||
private Request request;
|
||||
private static LWAAuthorizationSigner underTestSeller;
|
||||
private static LWAAuthorizationSigner underTestSellerless;
|
||||
|
||||
@Mock
|
||||
private OkHttpClient mockOkHttpClient;
|
||||
|
||||
@Mock
|
||||
private Call mockCall;
|
||||
|
||||
static {
|
||||
|
||||
underTestSeller = new LWAAuthorizationSigner(LWAAuthorizationCredentials.builder()
|
||||
|
@ -52,11 +72,12 @@ public class LWAAuthorizationSignerTest {
|
|||
.build());
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@Before @BeforeEach
|
||||
public void init() {
|
||||
request = new Request.Builder()
|
||||
.url("https://www.amazon.com/api")
|
||||
.build();
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
}
|
||||
|
||||
|
@ -78,8 +99,7 @@ public class LWAAuthorizationSignerTest {
|
|||
@MethodSource("lwaAuthSigner")
|
||||
public void requestLWAAccessTokenFromConfiguration(String sellerType, LWAAuthorizationSigner testAuthSigner) {
|
||||
LWAClient mockLWAClient = mock(LWAClient.class);
|
||||
ArgumentCaptor<LWAAccessTokenRequestMeta> lwaAccessTokenRequestMetaArgumentCaptor = ArgumentCaptor.forClass(
|
||||
LWAAccessTokenRequestMeta.class);
|
||||
ArgumentCaptor<LWAAccessTokenRequestMeta> lwaAccessTokenRequestMetaArgumentCaptor = ArgumentCaptor.forClass(LWAAccessTokenRequestMeta.class);
|
||||
|
||||
when(mockLWAClient.getAccessToken(lwaAccessTokenRequestMetaArgumentCaptor.capture()))
|
||||
.thenReturn("foo");
|
||||
|
@ -128,4 +148,44 @@ public class LWAAuthorizationSignerTest {
|
|||
testAuthSigner.setLwaClient(mockLWAClient);
|
||||
assertNotSame(request, testAuthSigner.sign(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnSignedRequestWithAccessTokenFromLWACache() throws IOException {
|
||||
LWAClient testLWAClient = new LWAClient(TEST_ENDPOINT);
|
||||
testLWAClient.setOkHttpClient(mockOkHttpClient);
|
||||
|
||||
when(mockOkHttpClient.newCall(any(Request.class)))
|
||||
.thenReturn(mockCall);
|
||||
when(mockCall.execute())
|
||||
.thenReturn(buildResponse(200, "Azta|foo", "120"))
|
||||
.thenReturn(buildResponse(200, "Azta|foo1", "1"));
|
||||
|
||||
LWAAccessTokenCache testLWACache = new LWAAccessTokenCacheImpl();
|
||||
LWAAuthorizationSigner testlwaSigner = new LWAAuthorizationSigner(LWAAuthorizationCredentials.builder()
|
||||
.clientId(TEST_CLIENT_ID)
|
||||
.clientSecret(TEST_CLIENT_SECRET)
|
||||
.refreshToken(TEST_REFRESH_TOKEN)
|
||||
.endpoint(TEST_ENDPOINT)
|
||||
.build() , testLWACache );
|
||||
|
||||
testlwaSigner.setLwaClient(testLWAClient);
|
||||
testLWAClient.setLWAAccessTokenCache(testLWACache);
|
||||
Request actualSignedRequest = testlwaSigner.sign(request);
|
||||
Request actualSignedSecondRequest = testlwaSigner.sign(request);
|
||||
|
||||
assertEquals("Azta|foo", actualSignedSecondRequest.header("x-amz-access-token"));
|
||||
}
|
||||
|
||||
private static Response buildResponse(int code, String accessToken, String expiryInSeconds) {
|
||||
ResponseBody responseBody = ResponseBody.create(EXPECTED_MEDIA_TYPE,
|
||||
String.format("{%s:%s,%s:%s}", "access_token", accessToken, "expires_in", expiryInSeconds));
|
||||
|
||||
return new Response.Builder()
|
||||
.request(new Request.Builder().url(TEST_ENDPOINT).build())
|
||||
.code(code)
|
||||
.body(responseBody)
|
||||
.protocol(Protocol.HTTP_1_1)
|
||||
.message("OK")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_MIGRATION_API;
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_NOTIFICATIONS_API;
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_MIGRATION_API;
|
||||
|
||||
public class LWAClientScopesSerializerDeserializerTest {
|
||||
private static final String TEST_SCOPE_1 = SCOPE_NOTIFICATIONS_API;
|
||||
|
|
|
@ -30,13 +30,14 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_MIGRATION_API;
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_NOTIFICATIONS_API;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_NOTIFICATIONS_API;
|
||||
import static com.amazon.SellingPartnerAPIAA.ScopeConstants.SCOPE_MIGRATION_API;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LWAClientTest {
|
||||
private static final String TEST_ENDPOINT = "https://www.amazon.com/api";
|
||||
|
@ -77,14 +78,12 @@ public class LWAClientTest {
|
|||
.build();
|
||||
}
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
@Before @BeforeEach
|
||||
public void init() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
underTest = new LWAClient(TEST_ENDPOINT);
|
||||
underTest.setOkHttpClient(mockOkHttpClient);
|
||||
|
||||
}
|
||||
|
||||
public static Stream<Arguments> lwaClient(){
|
||||
|
@ -170,9 +169,42 @@ public class LWAClientTest {
|
|||
});
|
||||
}
|
||||
|
||||
private static Response buildResponse(int code, String accessToken) {
|
||||
//Test for Access Token getting from cache
|
||||
@Test
|
||||
public void returnAccessTokenFromCache() throws IOException, InterruptedException {
|
||||
|
||||
when(mockOkHttpClient.newCall(any(Request.class)))
|
||||
.thenReturn(mockCall);
|
||||
when(mockCall.execute())
|
||||
.thenReturn(buildResponse(200, "Azta|foo", "120"))
|
||||
.thenThrow(IllegalStateException.class);
|
||||
underTest.setLWAAccessTokenCache(new LWAAccessTokenCacheImpl());
|
||||
|
||||
//First call should get from Endpoint
|
||||
assertEquals("Azta|foo", underTest.getAccessToken(lwaAccessTokenRequestMetaSeller));
|
||||
//Second call when the cache is still valid, if it goes to end point it will return IllegalStateException.
|
||||
assertEquals("Azta|foo", underTest.getAccessToken(lwaAccessTokenRequestMetaSeller));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnAccessTokenFromCacheWithExpiry() throws IOException, InterruptedException {
|
||||
LWAClient client = new LWAClient(TEST_ENDPOINT);
|
||||
client.setOkHttpClient(mockOkHttpClient);
|
||||
when(mockOkHttpClient.newCall(any(Request.class)))
|
||||
.thenReturn(mockCall);
|
||||
when(mockCall.execute())
|
||||
.thenReturn(buildResponse(200, "Azta|foo", "1"))
|
||||
.thenReturn(buildResponse(200, "Azta|foo1", "1"));
|
||||
|
||||
//First call should get from Endpoint
|
||||
assertEquals("Azta|foo", client.getAccessToken(lwaAccessTokenRequestMetaSeller));
|
||||
//Second call should again go to the endpoint because accesstoken is expired after expiry adjustment.
|
||||
assertEquals("Azta|foo1", client.getAccessToken(lwaAccessTokenRequestMetaSeller));
|
||||
}
|
||||
|
||||
private static Response buildResponse(int code, String accessToken, String expiryInSeconds) {
|
||||
ResponseBody responseBody = ResponseBody.create(EXPECTED_MEDIA_TYPE,
|
||||
String.format("{%s:%s}", "access_token", accessToken));
|
||||
String.format("{%s:%s,%s:%s}", "access_token", accessToken, "expires_in", expiryInSeconds));
|
||||
|
||||
return new Response.Builder()
|
||||
.request(new Request.Builder().url(TEST_ENDPOINT).build())
|
||||
|
@ -182,4 +214,8 @@ public class LWAClientTest {
|
|||
.message("OK")
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Response buildResponse(int code, String accessToken) {
|
||||
return buildResponse(code, accessToken, "3600");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue