Skip to content

Commit f9f816a

Browse files
fix: permit passing client metadata to signin (#2053)
Resolves: #2048
1 parent c0436c9 commit f9f816a

File tree

9 files changed

+232
-25
lines changed

9 files changed

+232
-25
lines changed

aws-android-sdk-cognitoidentityprovider/build.gradle

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ android {
1010
versionCode 1
1111
versionName '1.0'
1212
}
13+
14+
testOptions.unitTests.includeAndroidResources = true
1315
}
1416

1517
dependencies {
1618
api project(':aws-android-sdk-core')
1719
implementation 'com.amazonaws:aws-android-sdk-cognitoidentityprovider-asf:1.0.0'
18-
}
1920

21+
testImplementation 'junit:junit:4.13'
22+
testImplementation 'org.mockito:mockito-core:1.10.19'
23+
testImplementation 'org.robolectric:robolectric:4.3.1'
24+
testImplementation 'androidx.test:core:1.2.0'
25+
}

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.amazonaws.mobileconnectors.cognitoidentityprovider.handlers.AuthenticationHandler;
2525

2626
import java.util.Collections;
27+
import java.util.HashMap;
2728
import java.util.Map;
2829

2930
/**
@@ -47,17 +48,10 @@ public class AuthenticationContinuation implements CognitoIdentityProviderContin
4748
private final Context context;
4849
private final AuthenticationHandler callback;
4950
private final boolean runInBackground;
51+
private final Map<String, String> clientMetadata;
5052

5153
private AuthenticationDetails authenticationDetails = null;
52-
private Map<String, String> clientMetadata;
5354

54-
/**
55-
* Constructs a new continuation in the authentication process.
56-
*
57-
* @param user
58-
* @param runInBackground
59-
* @param callback
60-
*/
6155
/**
6256
* Constructs a new continuation in the authentication process.
6357
*
@@ -74,7 +68,7 @@ public AuthenticationContinuation(CognitoUser user,
7468
this.context = context;
7569
this.runInBackground = runInBackground;
7670
this.callback = callback;
77-
this.clientMetadata = Collections.emptyMap();
71+
this.clientMetadata = new HashMap<>();
7872
}
7973

8074
/**
@@ -84,8 +78,9 @@ public AuthenticationContinuation(CognitoUser user,
8478
* </p>
8579
* @return ClientMetadata
8680
*/
81+
@SuppressWarnings("unused")
8782
public Map<String, String> getClientMetaData() {
88-
return clientMetadata;
83+
return Collections.unmodifiableMap(clientMetadata);
8984
}
9085

9186
/**
@@ -94,14 +89,17 @@ public Map<String, String> getClientMetaData() {
9489
*/
9590
public void setClientMetaData(Map<String, String> clientMetadata) {
9691
this.clientMetadata.clear();
97-
this.clientMetadata.putAll(clientMetadata);
92+
if (clientMetadata != null) {
93+
this.clientMetadata.putAll(clientMetadata);
94+
}
9895
}
9996

10097
/**
10198
* Returns the parameters required for this continuation.
10299
*
103100
* @return
104101
*/
102+
@SuppressWarnings("JavaDoc")
105103
@Override
106104
public String getParameters() {
107105
return "AuthenticationDetails";

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class ChallengeContinuation implements CognitoIdentityProviderContinuatio
4646
*/
4747
public static final boolean RUN_IN_CURRENT = false;
4848

49+
protected final Map<String, String> challengeResponses;
4950
private final RespondToAuthChallengeResult challengeResult;
5051
private final Context context;
5152
private final String clientId;
@@ -54,8 +55,7 @@ public class ChallengeContinuation implements CognitoIdentityProviderContinuatio
5455
private final String username;
5556
private final AuthenticationHandler callback;
5657
private final boolean runInBackground;
57-
protected Map<String, String> challengeResponses;
58-
protected Map<String, String> clientMetaData;
58+
private final Map<String, String> clientMetaData;
5959

6060
/**
6161
* Constructs a continuation for a challenge to be presented to the user.
@@ -86,8 +86,8 @@ public ChallengeContinuation(CognitoUser user,
8686
this.username = username;
8787
this.callback = callback;
8888
this.runInBackground = runInBackground;
89-
challengeResponses = new HashMap<>();
90-
clientMetaData = new HashMap<>();
89+
this.challengeResponses = new HashMap<>();
90+
this.clientMetaData = new HashMap<>();
9191
}
9292

9393
/**
@@ -98,15 +98,18 @@ public ChallengeContinuation(CognitoUser user,
9898
* @return ClientMetadata
9999
*/
100100
public Map<String, String> getClientMetaData() {
101-
return clientMetaData;
101+
return Collections.unmodifiableMap(clientMetaData);
102102
}
103103

104104
/**
105105
* Mutator for <code>clientMetadata</code>.
106106
* @param clientMetaData MetaData to be passed as input to the lambda triggers.
107107
*/
108108
public void setClientMetaData(Map<String, String> clientMetaData) {
109-
this.clientMetaData = Collections.unmodifiableMap(clientMetaData);
109+
this.clientMetaData.clear();
110+
if (clientMetaData != null) {
111+
this.clientMetaData.putAll(clientMetaData);
112+
}
110113
}
111114

112115
/**
@@ -162,7 +165,7 @@ public void continueTask() {
162165
respondToAuthChallengeRequest.setSession(challengeResult.getSession());
163166
respondToAuthChallengeRequest.setClientId(clientId);
164167
respondToAuthChallengeRequest.setChallengeResponses(challengeResponses);
165-
if (clientMetaData != null) {
168+
if (!clientMetaData.isEmpty()) {
166169
respondToAuthChallengeRequest.setClientMetadata(clientMetaData);
167170
}
168171
if (runInBackground) {

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserCodeDeliveryDetails;
2222
import com.amazonaws.mobileconnectors.cognitoidentityprovider.handlers.ForgotPasswordHandler;
2323

24+
import java.util.HashMap;
2425
import java.util.Map;
2526

2627
/**
@@ -42,10 +43,10 @@ public class ForgotPasswordContinuation implements CognitoIdentityProviderContin
4243
private final CognitoUser user;
4344
private final CognitoUserCodeDeliveryDetails parameters;
4445
private final boolean runInBackground;
46+
private final Map<String, String> clientMetadata;
4547

4648
private String password = null;
4749
private String verificationCode = null;
48-
private Map<String, String> clientMetadata;
4950

5051
/**
5152
* Constructs a new Continuation for forgot password process.
@@ -63,6 +64,7 @@ public ForgotPasswordContinuation(CognitoUser user,
6364
this.user = user;
6465
this.parameters = parameters;
6566
this.runInBackground = runInBackground;
67+
this.clientMetadata = new HashMap<>();
6668
}
6769

6870
/**
@@ -110,6 +112,9 @@ public void setVerificationCode(String verificationCode) {
110112
* @param clientMetadata
111113
*/
112114
public void setClientMetadata(final Map<String, String> clientMetadata) {
113-
this.clientMetadata = clientMetadata;
115+
this.clientMetadata.clear();
116+
if (clientMetadata != null) {
117+
this.clientMetadata.putAll(clientMetadata);
118+
}
114119
}
115120
}

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.amazonaws.services.cognitoidentityprovider.model.RespondToAuthChallengeResult;
2828

2929
import java.util.Collections;
30+
import java.util.HashMap;
3031
import java.util.Map;
3132

3233
/**
@@ -49,8 +50,9 @@ public class MultiFactorAuthenticationContinuation implements CognitoIdentityPro
4950
private final RespondToAuthChallengeResult challenge;
5051
private final boolean runInBackground;
5152
private final AuthenticationHandler callback;
53+
private final Map<String, String> clientMetadata;
54+
5255
private String mfaCode = null;
53-
private Map<String, String> clientMetadata;
5456

5557
/**
5658
* Constructs a multi-factor authentication continuation.
@@ -71,7 +73,7 @@ public MultiFactorAuthenticationContinuation(CognitoUser user,
7173
this.callback = callback;
7274
this.runInBackground = runInBackground;
7375
this.challenge = challenge;
74-
this.clientMetadata = Collections.emptyMap();
76+
this.clientMetadata = new HashMap<>();
7577
}
7678

7779
/**
@@ -82,7 +84,7 @@ public MultiFactorAuthenticationContinuation(CognitoUser user,
8284
* @return ClientMetadata
8385
*/
8486
public Map<String, String> getClientMetaData() {
85-
return clientMetadata;
87+
return Collections.unmodifiableMap(clientMetadata);
8688
}
8789

8890
/**
@@ -91,7 +93,9 @@ public Map<String, String> getClientMetaData() {
9193
*/
9294
public void setClientMetaData(Map<String, String> clientMetadata) {
9395
this.clientMetadata.clear();
94-
this.clientMetadata.putAll(clientMetadata);
96+
if (clientMetadata != null) {
97+
this.clientMetadata.putAll(clientMetadata);
98+
}
9599
}
96100

97101
/**
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<manifest xmlns:tools="http://schemas.android.com/tools"
2+
package="com.amazonaws.services.cognitoidentityprovider">
3+
<uses-sdk tools:overrideLibrary="androidx.test.core, androidx.test" />
4+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Amazon Software License (the "License").
5+
* You may not use this file except in compliance with the
6+
* License. A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/asl/
9+
*
10+
* or in the "license" file accompanying this file. This file is
11+
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
* CONDITIONS OF ANY KIND, express or implied. See the License
13+
* for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations;
18+
19+
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser;
20+
import com.amazonaws.mobileconnectors.cognitoidentityprovider.handlers.AuthenticationHandler;
21+
22+
import org.junit.Test;
23+
import org.junit.runner.RunWith;
24+
import org.robolectric.RobolectricTestRunner;
25+
import org.robolectric.annotation.Config;
26+
27+
import java.util.Collections;
28+
import java.util.Map;
29+
import java.util.concurrent.TimeUnit;
30+
31+
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
32+
import static org.junit.Assert.assertEquals;
33+
import static org.junit.Assert.assertTrue;
34+
import static org.mockito.Matchers.eq;
35+
import static org.mockito.Mockito.doReturn;
36+
import static org.mockito.Mockito.mock;
37+
38+
/**
39+
* Tests the {@link AuthenticationContinuation}.
40+
*/
41+
@RunWith(RobolectricTestRunner.class)
42+
@Config(manifest= Config.NONE, sdk = 27)
43+
public final class AuthenticationContinuationTest {
44+
/**
45+
* What happens when we try to pass client metadata into the handler?
46+
* @throws InterruptedException If {@link CountDownRunnable} is interrupted while pending result
47+
*/
48+
@Test
49+
public void setMetadataAndContinueTask() throws InterruptedException {
50+
AuthenticationHandler handler = mock(AuthenticationHandler.class);
51+
CognitoUser user = mock(CognitoUser.class);
52+
53+
AuthenticationDetails authenticationDetails = mock(AuthenticationDetails.class);
54+
Map<String, String> metadata = Collections.singletonMap("blacklives", "matter");
55+
AuthenticationContinuation authenticationContinuation =
56+
new AuthenticationContinuation(user, getApplicationContext(), false, handler);
57+
authenticationContinuation.setClientMetaData(metadata);
58+
authenticationContinuation.setAuthenticationDetails(authenticationDetails);
59+
60+
CountDownRunnable countDownRunnable = CountDownRunnable.create();
61+
doReturn(countDownRunnable)
62+
.when(user)
63+
.initiateUserAuthentication(eq(metadata), eq(authenticationDetails), eq(handler), eq(false));
64+
65+
// Act: continue task
66+
authenticationContinuation.continueTask();
67+
68+
// Assert: action was invoked
69+
assertTrue(countDownRunnable.await(5, TimeUnit.SECONDS));
70+
assertEquals(metadata, authenticationContinuation.getClientMetaData());
71+
}
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2020 Amazon.com,
3+
* Inc. or its affiliates. All Rights Reserved.
4+
*
5+
* Licensed under the Amazon Software License (the "License").
6+
* You may not use this file except in compliance with the
7+
* License. A copy of the License is located at
8+
*
9+
* http://aws.amazon.com/asl/
10+
*
11+
* or in the "license" file accompanying this file. This file is
12+
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
13+
* CONDITIONS OF ANY KIND, express or implied. See the License
14+
* for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations;
19+
20+
import java.util.concurrent.CountDownLatch;
21+
22+
/**
23+
* A {@link CountDownLatch} which implements the {@link Runnable} contract by
24+
* counting down the latch whenever {@link Runnable#run()} is invoked.
25+
*
26+
* A CountDownRunnable always starts at 1.
27+
*/
28+
final class CountDownRunnable extends CountDownLatch implements Runnable {
29+
private CountDownRunnable() {
30+
super(1);
31+
}
32+
33+
static CountDownRunnable create() {
34+
return new CountDownRunnable();
35+
}
36+
37+
@Override
38+
public void run() {
39+
super.countDown();
40+
}
41+
}

0 commit comments

Comments
 (0)