Skip to content

Commit 6b4a34e

Browse files
authored
Adds override for User Agent in AWSMobileClient (#2024)
Currently if the user agent value is set in the client config, it may be appended to other values. This PR adds the ability to set a user agent override value which will ensure that nothing is appended on to it and it is sent as the final user agent. The reason for this change is that Amplify Auth uses AWSMobileClient which uses underlying User Pool and Identity Pool SDKs. This is how user agents are currently handled: Someone uses aws-android-sdk-auth-userpools: User Agent = userpools_UA Someone uses aws-android-sdk-cognitoidentityprovider: User Agent = cognitoidentityprovider_UA Someone uses AWSMobileClient: Methods using userpools: User Agent = userpools_UA + AMC_string Methods using cognito identity provider: User Agent = cognitoidentityprovider_UA + AMC_string Until now, someone using Amplify Auth would have the same user agent sent as AWSMobileClient because it uses AWSMobileClient. This is a problem since Amplify Auth usage can't be correctly attributed. The solution requested by the product team is that someone using Amplify Auth has the Amplify user agent sent, completely overriding any of the other user agents the SDKs currently use.
1 parent f6b2a70 commit 6b4a34e

File tree

8 files changed

+136
-53
lines changed

8 files changed

+136
-53
lines changed

aws-android-sdk-auth-core/src/main/java/com/amazonaws/mobile/auth/core/IdentityManager.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ public IdentityManager(final Context context,
223223
final AWSConfiguration awsConfiguration) {
224224
this.appContext = context.getApplicationContext();
225225
this.awsConfiguration = awsConfiguration;
226-
this.clientConfiguration = new ClientConfiguration().withUserAgent(awsConfiguration.getUserAgent());
226+
this.clientConfiguration = new ClientConfiguration()
227+
.withUserAgent(awsConfiguration.getUserAgent())
228+
.withUserAgentOverride(awsConfiguration.getUserAgentOverride());
227229
this.credentialsProviderHolder = new AWSCredentialsProviderHolder();
228230
createCredentialsProvider(this.appContext, this.clientConfiguration);
229231
this.awsKeyValueStore = new AWSKeyValueStore(appContext, SHARED_PREF_NAME, isPersistenceEnabled);
@@ -905,7 +907,6 @@ public void login(final Context context,
905907
*/
906908
private void createCredentialsProvider(final Context context,
907909
final ClientConfiguration clientConfiguration) {
908-
909910
Log.d(LOG_TAG, "Creating the Cognito Caching Credentials Provider "
910911
+ "with a refreshing Cognito Identity Provider.");
911912

@@ -929,9 +930,16 @@ private void createCredentialsProvider(final Context context,
929930
new AWSRefreshingCognitoIdentityProvider(null, poolId,
930931
clientConfiguration, cognitoIdentityRegion);
931932

932-
final CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider = new CognitoCachingCredentialsProvider(context, refreshingCredentialsProvider,
933-
cognitoIdentityRegion, clientConfiguration);
933+
final CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider =
934+
new CognitoCachingCredentialsProvider(
935+
context,
936+
refreshingCredentialsProvider,
937+
cognitoIdentityRegion,
938+
clientConfiguration);
934939
cognitoCachingCredentialsProvider.setPersistenceEnabled(isPersistenceEnabled);
940+
if (clientConfiguration.getUserAgentOverride() != null) {
941+
cognitoCachingCredentialsProvider.setUserAgentOverride(clientConfiguration.getUserAgentOverride());
942+
}
935943
credentialsProviderHolder.setUnderlyingProvider(cognitoCachingCredentialsProvider);
936944
}
937945

aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider/CognitoUserPool.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ public CognitoUserPool(Context context, AWSConfiguration awsConfiguration) {
189189

190190
final ClientConfiguration clientConfig = new ClientConfiguration();
191191
clientConfig.setUserAgent(awsConfiguration.getUserAgent());
192+
clientConfig.setUserAgentOverride(awsConfiguration.getUserAgentOverride());
192193
this.client = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), clientConfig);
193194
this.client.setRegion(com.amazonaws.regions.Region.getRegion(Regions.fromName(userPoolConfiguration.getString("Region"))));
194195
} catch (Exception e) {

aws-android-sdk-core/src/main/java/com/amazonaws/ClientConfiguration.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ public class ClientConfiguration {
5959
/** The HTTP user agent header passed with all HTTP requests. */
6060
private String userAgent = DEFAULT_USER_AGENT;
6161

62+
/**
63+
* The {@link #userAgent} string is sometimes combined with other strings. If this property is set, it instructs the
64+
* client to only use this as the full user agent string.
65+
*/
66+
private String userAgentOverride;
67+
6268
/**
6369
* The maximum number of times that a retryable failed request (ex: a 5xx
6470
* response from a service) will be retried. Or -1 if the user has not
@@ -193,6 +199,7 @@ public ClientConfiguration(ClientConfiguration other) {
193199
this.preemptiveBasicProxyAuth = other.preemptiveBasicProxyAuth;
194200
this.socketTimeout = other.socketTimeout;
195201
this.userAgent = other.userAgent;
202+
this.userAgentOverride = other.userAgentOverride;
196203
this.socketReceiveBufferSizeHint = other.socketReceiveBufferSizeHint;
197204
this.socketSendBufferSizeHint = other.socketSendBufferSizeHint;
198205
this.signerOverride = other.signerOverride;
@@ -326,6 +333,39 @@ public ClientConfiguration withUserAgent(String userAgent) {
326333
return this;
327334
}
328335

336+
/**
337+
* The {@link #userAgent} string is sometimes combined with other strings. If this property is set, it instructs the
338+
* client to only use this as the full user agent string.
339+
*
340+
* @return The string to use as the full user agent when sending requests.
341+
*/
342+
public String getUserAgentOverride() {
343+
return userAgentOverride;
344+
}
345+
346+
/**
347+
* The {@link #userAgent} string is sometimes combined with other strings. If this property is set, it instructs the
348+
* client to only use this as the full user agent string.
349+
*
350+
* @param userAgentOverride The string to use as the full user agent when sending requests.
351+
*/
352+
public void setUserAgentOverride(String userAgentOverride) {
353+
this.userAgentOverride = userAgentOverride;
354+
}
355+
356+
/**
357+
* The {@link #userAgent} string is sometimes combined with other strings. If this property is set, it instructs the
358+
* client to only use this as the full user agent string.
359+
*
360+
* @param userAgentOverride The string to use as the full user agent when sending requests.
361+
* @return The updated ClientConfiguration object.
362+
*/
363+
@SuppressWarnings("checkstyle:hiddenfield")
364+
public ClientConfiguration withUserAgentOverride(String userAgentOverride) {
365+
setUserAgentOverride(userAgentOverride);
366+
return this;
367+
}
368+
329369
/**
330370
* Returns the optional local address the client will bind to.
331371
*

aws-android-sdk-core/src/main/java/com/amazonaws/auth/CognitoCachingCredentialsProvider.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ public void identityChanged(String oldIdentityId, String newIdentityId) {
110110
}
111111
};
112112
private boolean isPersistenceEnabled = true;
113+
private String userAgentOverride;
113114

114115
/**
115116
* Constructs a new {@link CognitoCachingCredentialsProvider}, which will
@@ -660,7 +661,11 @@ private void saveIdentityId(String identityId) {
660661

661662
@Override
662663
protected String getUserAgent() {
663-
return USER_AGENT;
664+
if (userAgentOverride != null) {
665+
return userAgentOverride;
666+
} else {
667+
return USER_AGENT;
668+
}
664669
}
665670

666671
// To support multiple identity pools in the same app, namespacing the keys
@@ -695,4 +700,14 @@ public void setPersistenceEnabled(boolean isPersistenceEnabled) {
695700
this.isPersistenceEnabled = isPersistenceEnabled;
696701
this.awsKeyValueStore.setPersistenceEnabled(isPersistenceEnabled);
697702
}
703+
704+
/**
705+
* The user agent string is sometimes combined with other strings. If this property is set, it instructs the
706+
* client to only use this as the full user agent string.
707+
*
708+
* @param userAgentOverride The string to use as the full user agent when sending requests.
709+
*/
710+
public void setUserAgentOverride(String userAgentOverride) {
711+
this.userAgentOverride = userAgentOverride;
712+
}
698713
}

aws-android-sdk-core/src/main/java/com/amazonaws/http/AmazonHttpClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,8 @@ void setUserAgent(Request<?> request) {
534534
if (!ClientConfiguration.DEFAULT_USER_AGENT.equals(config.getUserAgent())) {
535535
userAgent = createUserAgentString(userAgent, config.getUserAgent());
536536
}
537-
request.addHeader(HEADER_USER_AGENT, userAgent);
537+
request.addHeader(HEADER_USER_AGENT,
538+
config.getUserAgentOverride() != null ? config.getUserAgentOverride() : userAgent);
538539
}
539540

540541
/**

aws-android-sdk-core/src/main/java/com/amazonaws/mobile/config/AWSConfiguration.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,20 @@ public String getUserAgent() {
181181
}
182182
}
183183

184+
/**
185+
* The user agent is sometimes combined with other strings. If this property is set, it instructs the
186+
* client to only use this as the full user agent string.
187+
*
188+
* @return The user agent override specified in the configuration file.
189+
*/
190+
public String getUserAgentOverride() {
191+
try {
192+
return this.mJSONObject.getString("UserAgentOverride");
193+
} catch (JSONException je) {
194+
return null;
195+
}
196+
}
197+
184198
/**
185199
* Change the settings that are being read in. This is "Default" by default.
186200
*

aws-android-sdk-mobile-client/src/main/java/com/amazonaws/mobile/client/AWSMobileClient.java

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,9 @@ public final class AWSMobileClient implements AWSCredentialsProvider {
166166
* Log Tag.
167167
*/
168168
private static final String TAG = AWSMobileClient.class.getSimpleName();
169-
public static final String USER_AGENT = "AWSMobileClient";
169+
public static final String DEFAULT_USER_AGENT = "AWSMobileClient";
170170

171+
static final String AUTH_KEY = "Auth";
171172
static final String SHARED_PREFERENCES_KEY = "com.amazonaws.mobile.client";
172173
static final String PROVIDER_KEY = "provider";
173174
static final String TOKEN_KEY = "token";
@@ -266,6 +267,7 @@ public final class AWSMobileClient implements AWSCredentialsProvider {
266267
Auth hostedUI;
267268
OAuth2Client mOAuth2Client;
268269
String mUserPoolPoolId;
270+
String userAgentOverride;
269271

270272
enum SignInMode {
271273
SIGN_IN("0"),
@@ -464,10 +466,10 @@ public void run() {
464466
// Read Persistence key from the awsconfiguration.json and set the flag
465467
// appropriately.
466468
try {
467-
if (awsConfiguration.optJsonObject("Auth") != null &&
468-
awsConfiguration.optJsonObject("Auth").has("Persistence")) {
469+
if (awsConfiguration.optJsonObject(AUTH_KEY) != null &&
470+
awsConfiguration.optJsonObject(AUTH_KEY).has("Persistence")) {
469471
mIsPersistenceEnabled = awsConfiguration
470-
.optJsonObject("Auth")
472+
.optJsonObject(AUTH_KEY)
471473
.getBoolean("Persistence");
472474
}
473475
} catch (final Exception ex) {
@@ -476,6 +478,7 @@ public void run() {
476478
return;
477479
}
478480

481+
userAgentOverride = awsConfiguration.getUserAgentOverride();
479482
mContext = context.getApplicationContext();
480483
mStore = new AWSMobileClientStore(AWSMobileClient.this);
481484

@@ -525,15 +528,21 @@ public void onUserSignedOut() {
525528
final String poolId = identityPoolJSON.getString("PoolId");
526529
final String regionStr = identityPoolJSON.getString("Region");
527530
final ClientConfiguration clientConfig = new ClientConfiguration();
528-
clientConfig.setUserAgent(USER_AGENT + " " + awsConfiguration.getUserAgent());
531+
clientConfig.setUserAgent(DEFAULT_USER_AGENT + " " + awsConfiguration.getUserAgent());
532+
if (userAgentOverride != null) {
533+
clientConfig.setUserAgentOverride(userAgentOverride);
534+
}
529535
AmazonCognitoIdentityClient cibClient =
530-
new AmazonCognitoIdentityClient(new AnonymousAWSCredentials());
536+
new AmazonCognitoIdentityClient(new AnonymousAWSCredentials(), clientConfig);
531537
cibClient.setRegion(Region.getRegion(regionStr));
532538
provider = new AWSMobileClientCognitoIdentityProvider(
533539
null, poolId, cibClient);
534540
cognitoIdentity = new CognitoCachingCredentialsProvider(
535541
mContext, provider, Regions.fromName(regionStr));
536542
cognitoIdentity.setPersistenceEnabled(mIsPersistenceEnabled);
543+
if (userAgentOverride != null) {
544+
cognitoIdentity.setUserAgentOverride(userAgentOverride);
545+
}
537546
} catch (Exception e) {
538547
callback.onError(new RuntimeException("Failed to initialize Cognito Identity; please check your awsconfiguration.json", e));
539548
return;
@@ -549,7 +558,10 @@ public void onUserSignedOut() {
549558
final String pinpointEndpointId = CognitoPinpointSharedContext.getPinpointEndpoint(context, userPoolJSON.optString("PinpointAppId"));
550559

551560
final ClientConfiguration clientConfig = new ClientConfiguration();
552-
clientConfig.setUserAgent(USER_AGENT + " " + awsConfiguration.getUserAgent());
561+
clientConfig.setUserAgent(DEFAULT_USER_AGENT + " " + awsConfiguration.getUserAgent());
562+
if (userAgentOverride != null) {
563+
clientConfig.setUserAgentOverride(userAgentOverride);
564+
}
553565
userpoolLL =
554566
new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), clientConfig);
555567
userpoolLL.setRegion(com.amazonaws.regions.Region.getRegion(Regions.fromName(userPoolJSON.getString("Region"))));
@@ -575,6 +587,7 @@ public void onUserSignedOut() {
575587
Log.d(TAG, "initialize: OAuth2 client detected");
576588
mOAuth2Client = new OAuth2Client(mContext, AWSMobileClient.this);
577589
mOAuth2Client.setPersistenceEnabled(mIsPersistenceEnabled);
590+
mOAuth2Client.setUserAgentOverride(userAgentOverride);
578591
} else {
579592
_initializeHostedUI(hostedUIJSON);
580593
}
@@ -638,7 +651,7 @@ JSONObject getHostedUIJSONFromJSON() {
638651
}
639652

640653
JSONObject getHostedUIJSONFromJSON(final AWSConfiguration awsConfig) {
641-
final JSONObject mobileClientJSON = awsConfig.optJsonObject("Auth");
654+
final JSONObject mobileClientJSON = awsConfig.optJsonObject(AUTH_KEY);
642655
if (mobileClientJSON != null && mobileClientJSON.has("OAuth")) {
643656
try {
644657
JSONObject hostedUIJSONFromJSON = mobileClientJSON.getJSONObject("OAuth");
@@ -1192,18 +1205,20 @@ public void onSuccess(CognitoUserSession userSession, CognitoDevice newDevice) {
11921205
public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) {
11931206
Log.d(TAG, "Sending password.");
11941207
try {
1195-
if (awsConfiguration.optJsonObject("Auth") != null &&
1196-
awsConfiguration.optJsonObject("Auth").has("authenticationFlowType") &&
1197-
awsConfiguration.optJsonObject("Auth").getString("authenticationFlowType").equals("CUSTOM_AUTH")
1208+
if (
1209+
awsConfiguration.optJsonObject(AUTH_KEY) != null &&
1210+
awsConfiguration.optJsonObject(AUTH_KEY).has("authenticationFlowType") &&
1211+
awsConfiguration.optJsonObject(AUTH_KEY).getString("authenticationFlowType").equals("CUSTOM_AUTH")
11981212
) {
1199-
final HashMap<String, String> authParameters = new HashMap<String,String>();
1213+
final HashMap<String, String> authParameters = new HashMap<String, String>();
12001214
authenticationContinuation.setAuthenticationDetails(new AuthenticationDetails(username, password, authParameters, validationData));
12011215
} else {
12021216
authenticationContinuation.setAuthenticationDetails(new AuthenticationDetails(username, password, validationData));
12031217
}
12041218
} catch (JSONException e) {
12051219
e.printStackTrace();
12061220
}
1221+
12071222
authenticationContinuation.continueTask();
12081223
}
12091224

@@ -1451,9 +1466,9 @@ public void signOut() {
14511466
mFederatedLoginsMap.clear();
14521467
mStore.clear();
14531468
String hostedUIJSON = null;
1454-
if (awsConfiguration.optJsonObject("Auth") != null && awsConfiguration.optJsonObject("Auth").has("OAuth")) {
1469+
if (awsConfiguration.optJsonObject(AUTH_KEY) != null && awsConfiguration.optJsonObject(AUTH_KEY).has("OAuth")) {
14551470
try {
1456-
hostedUIJSON = awsConfiguration.optJsonObject("Auth").getJSONObject("OAuth").toString();
1471+
hostedUIJSON = awsConfiguration.optJsonObject(AUTH_KEY).getJSONObject("OAuth").toString();
14571472
} catch (JSONException e) {
14581473
e.printStackTrace();
14591474
}
@@ -3815,32 +3830,6 @@ class AWSMobileClientCognitoIdentityProvider extends AWSAbstractCognitoIdentityP
38153830

38163831
boolean isDeveloperAuthenticated;
38173832

3818-
/**
3819-
* An extension of the AbstractCognitoProvider that is used to communicate
3820-
* with Cognito.
3821-
*
3822-
* @param accountId the account id of the developer
3823-
* @param identityPoolId the identity pool id of the app/user in question
3824-
*/
3825-
public AWSMobileClientCognitoIdentityProvider(String accountId, String identityPoolId) {
3826-
this(accountId, identityPoolId, new ClientConfiguration());
3827-
}
3828-
3829-
/**
3830-
* An extension of the AbstractCognitoProvider that is used to communicate
3831-
* with Cognito.
3832-
*
3833-
* @param accountId the account id of the developer
3834-
* @param identityPoolId the identity pool id of the app/user in question
3835-
* @param clientConfiguration the configuration to apply to service clients
3836-
* created
3837-
*/
3838-
public AWSMobileClientCognitoIdentityProvider(String accountId, String identityPoolId,
3839-
ClientConfiguration clientConfiguration) {
3840-
this(accountId, identityPoolId, new AmazonCognitoIdentityClient
3841-
(new AnonymousAWSCredentials(), clientConfiguration));
3842-
}
3843-
38443833
/**
38453834
* An extension of the AbstractCognitoProvider that is used to communicate
38463835
* with Cognito.
@@ -3857,7 +3846,7 @@ public AWSMobileClientCognitoIdentityProvider(String accountId, String identityP
38573846

38583847
@Override
38593848
protected String getUserAgent() {
3860-
return "AWSMobileClient";
3849+
return AWSMobileClient.DEFAULT_USER_AGENT;
38613850
}
38623851

38633852
/**

0 commit comments

Comments
 (0)