Skip to content

Commit 2098c3c

Browse files
committed
[CognitoUserPools] Add support for password verifier challenge in arbitrary flow
The password verifier challenge was previously thought to only occur in a certain flow, this changes that limitation
1 parent de460b8 commit 2098c3c

File tree

1 file changed

+77
-22
lines changed
  • aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider

1 file changed

+77
-22
lines changed

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

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2271,7 +2271,7 @@ public Runnable respondToChallenge(final RespondToAuthChallengeRequest challenge
22712271
}
22722272
final RespondToAuthChallengeResult challenge = cognitoIdentityProviderClient
22732273
.respondToAuthChallenge(challengeResponse);
2274-
return handleChallenge(challenge, callback, runInBackground);
2274+
return handleChallenge(challenge, null, callback, runInBackground);
22752275
} catch (final ResourceNotFoundException rna) {
22762276
final CognitoUser cognitoUser = this;
22772277
if (rna.getMessage().contains("Device")) {
@@ -2334,7 +2334,7 @@ private Runnable startWithUserSrpAuth(final AuthenticationDetails authentication
23342334
return respondToChallenge(challengeRequest, callback, runInBackground);
23352335
}
23362336
}
2337-
return handleChallenge(initiateAuthResult, callback, runInBackground);
2337+
return handleChallenge(initiateAuthResult, authenticationDetails, callback, runInBackground);
23382338
} catch (final ResourceNotFoundException rna) {
23392339
final CognitoUser cognitoUser = this;
23402340
if (rna.getMessage().contains("Device")) {
@@ -2385,7 +2385,7 @@ private Runnable startWithCustomAuth(final AuthenticationDetails authenticationD
23852385
try {
23862386
final InitiateAuthResult initiateAuthResult = cognitoIdentityProviderClient
23872387
.initiateAuth(initiateAuthRequest);
2388-
return handleChallenge(initiateAuthResult, callback, runInBackground);
2388+
return handleChallenge(initiateAuthResult, authenticationDetails, callback, runInBackground);
23892389
} catch (final Exception e) {
23902390
return new Runnable() {
23912391
@Override
@@ -2412,13 +2412,16 @@ public void run() {
24122412
*
24132413
* @param challenge REQUIRED: Current challenge details,
24142414
* {@link RespondToAuthChallengeResult}.
2415+
* @param authenticationDetails OPTIONAL: This is used in the PASSWORD_VERIFIER challenge
24152416
* @param callback REQUIRED: {@link AuthenticationDetails} callback.
24162417
* @param runInBackground REQUIRED: Boolean to indicate the current
24172418
* threading.
24182419
* @return {@link Runnable} for the next step in user authentication.
24192420
*/
24202421
private Runnable handleChallenge(final RespondToAuthChallengeResult challenge,
2421-
final AuthenticationHandler callback, final boolean runInBackground) {
2422+
final AuthenticationDetails authenticationDetails,
2423+
final AuthenticationHandler callback,
2424+
final boolean runInBackground) {
24222425
Runnable nextTask;
24232426
final CognitoUser cognitoUser = this;
24242427
nextTask = new Runnable() {
@@ -2471,7 +2474,25 @@ public void run() {
24712474
}
24722475
}
24732476
} else if (CognitoServiceConstants.CHLG_TYPE_USER_PASSWORD_VERIFIER.equals(challengeName)) {
2474-
return nextTask;
2477+
return new Runnable() {
2478+
@Override
2479+
public void run() {
2480+
final AuthenticationHelper authenticationHelper = new AuthenticationHelper(
2481+
pool.getUserPoolId());
2482+
final Map<String, String> challengeParameters = challenge.getChallengeParameters();
2483+
cognitoIdentityProviderClient.respondToAuthChallenge(userSrpAuthRequest(
2484+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_USERNAME),
2485+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_USER_ID_FOR_SRP),
2486+
authenticationDetails.getPassword(),
2487+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_SRP_B),
2488+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_SALT),
2489+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_SECRET_BLOCK),
2490+
challenge.getChallengeName(),
2491+
challenge.getSession(),
2492+
authenticationHelper
2493+
));
2494+
}
2495+
};
24752496
} else if (CognitoServiceConstants.CHLG_TYPE_SMS_MFA.equals(challengeName)
24762497
|| CognitoServiceConstants.CHLG_TYPE_SOFTWARE_TOKEN_MFA.equals(challengeName)) {
24772498
final MultiFactorAuthenticationContinuation multiFactorAuthenticationContinuation = new MultiFactorAuthenticationContinuation(
@@ -2541,14 +2562,16 @@ public void run() {
25412562
* @return {@link Runnable} for the next step in user authentication.
25422563
*/
25432564
private Runnable handleChallenge(final InitiateAuthResult authResult,
2544-
final AuthenticationHandler callback, final boolean runInBackground) {
2565+
final AuthenticationDetails authenticationDetails,
2566+
final AuthenticationHandler callback,
2567+
final boolean runInBackground) {
25452568
try {
25462569
final RespondToAuthChallengeResult challenge = new RespondToAuthChallengeResult();
25472570
challenge.setChallengeName(authResult.getChallengeName());
25482571
challenge.setSession(authResult.getSession());
25492572
challenge.setAuthenticationResult(authResult.getAuthenticationResult());
25502573
challenge.setChallengeParameters(authResult.getChallengeParameters());
2551-
return handleChallenge(challenge, callback, runInBackground);
2574+
return handleChallenge(challenge, authenticationDetails, callback, runInBackground);
25522575
} catch (final Exception e) {
25532576
return new Runnable() {
25542577
@Override
@@ -2578,7 +2601,7 @@ private Runnable startWithUserPasswordAuth(final AuthenticationDetails authentic
25782601
.initiateAuth(initiateAuthRequest);
25792602
this.usernameInternal = initiateAuthResult.getChallengeParameters()
25802603
.get(CognitoServiceConstants.CHLG_PARAM_USER_ID_FOR_SRP);
2581-
return handleChallenge(initiateAuthResult, callback, runInBackground);
2604+
return handleChallenge(initiateAuthResult, authenticationDetails, callback, runInBackground);
25822605
} catch (final Exception e) {
25832606
return new Runnable() {
25842607
@Override
@@ -2658,9 +2681,9 @@ private Runnable deviceSrpAuthentication(final RespondToAuthChallengeResult chal
26582681
authenticationHelper);
26592682
final RespondToAuthChallengeResult deviceSRPAuthResult = cognitoIdentityProviderClient
26602683
.respondToAuthChallenge(challengeResponse);
2661-
return handleChallenge(deviceSRPAuthResult, callback, runInBackground);
2684+
return handleChallenge(deviceSRPAuthResult, null, callback, runInBackground);
26622685
} else {
2663-
return handleChallenge(initiateDeviceAuthResult, callback, runInBackground);
2686+
return handleChallenge(initiateDeviceAuthResult, null, callback, runInBackground);
26642687
}
26652688
} catch (final NotAuthorizedException na) {
26662689
final CognitoUser cognitoUser = this;
@@ -2852,22 +2875,55 @@ private InitiateAuthRequest initiateRefreshTokenAuthRequest(CognitoUserSession c
28522875
private RespondToAuthChallengeRequest userSrpAuthRequest(InitiateAuthResult challenge,
28532876
AuthenticationDetails authenticationDetails,
28542877
AuthenticationHelper authenticationHelper) {
2855-
final String userIdForSRP = challenge.getChallengeParameters()
2856-
.get(CognitoServiceConstants.CHLG_PARAM_USER_ID_FOR_SRP);
2857-
this.usernameInternal = challenge.getChallengeParameters()
2858-
.get(CognitoServiceConstants.CHLG_PARAM_USERNAME);
2878+
final Map<String, String> challengeParameters = challenge.getChallengeParameters();
2879+
return userSrpAuthRequest(
2880+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_USERNAME),
2881+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_USER_ID_FOR_SRP),
2882+
authenticationDetails.getPassword(),
2883+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_SRP_B),
2884+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_SALT),
2885+
challengeParameters.get(CognitoServiceConstants.CHLG_PARAM_SECRET_BLOCK),
2886+
challenge.getChallengeName(),
2887+
challenge.getSession(),
2888+
authenticationHelper
2889+
);
2890+
}
2891+
2892+
/**
2893+
* Creates response for the second step of the SRP authentication.
2894+
*
2895+
* @param userId returned by service
2896+
* @param userIdForSRP returned by service
2897+
* @param password maintained locally
2898+
* @param srpBString returned by service
2899+
* @param saltString returned by service
2900+
* @param secretBlockString returned by service
2901+
* @param challengeName returned by service
2902+
* @param session returned by service
2903+
* @return {@link RespondToAuthChallengeRequest}.
2904+
*/
2905+
private RespondToAuthChallengeRequest userSrpAuthRequest(final String userId,
2906+
final String userIdForSRP,
2907+
final String password,
2908+
final String srpBString,
2909+
final String saltString,
2910+
final String secretBlockString,
2911+
final String challengeName,
2912+
final String session,
2913+
final AuthenticationHelper authenticationHelper) {
2914+
this.usernameInternal = userId;
28592915
this.deviceKey = CognitoDeviceHelper.getDeviceKey(usernameInternal, pool.getUserPoolId(),
28602916
context);
28612917
secretHash = CognitoSecretHash.getSecretHash(usernameInternal, clientId, clientSecret);
28622918

2863-
final BigInteger srpB = new BigInteger(challenge.getChallengeParameters().get("SRP_B"), 16);
2919+
final BigInteger srpB = new BigInteger(srpBString, 16);
28642920
if (srpB.mod(AuthenticationHelper.N).equals(BigInteger.ZERO)) {
28652921
throw new CognitoInternalErrorException("SRP error, B cannot be zero");
28662922
}
28672923

2868-
final BigInteger salt = new BigInteger(challenge.getChallengeParameters().get("SALT"), 16);
2924+
final BigInteger salt = new BigInteger(saltString, 16);
28692925
final byte[] key = authenticationHelper.getPasswordAuthenticationKey(userIdForSRP,
2870-
authenticationDetails.getPassword(), srpB, salt);
2926+
password, srpB, salt);
28712927

28722928
final Date timestamp = new Date();
28732929
byte[] hmac;
@@ -2879,7 +2935,7 @@ private RespondToAuthChallengeRequest userSrpAuthRequest(InitiateAuthResult chal
28792935
mac.update(pool.getUserPoolId().split("_", 2)[1].getBytes(StringUtils.UTF8));
28802936
mac.update(userIdForSRP.getBytes(StringUtils.UTF8));
28812937
final byte[] secretBlock = Base64
2882-
.decode(challenge.getChallengeParameters().get("SECRET_BLOCK"));
2938+
.decode(secretBlockString);
28832939
mac.update(secretBlock);
28842940

28852941
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
@@ -2895,8 +2951,7 @@ private RespondToAuthChallengeRequest userSrpAuthRequest(InitiateAuthResult chal
28952951

28962952
final Map<String, String> srpAuthResponses = new HashMap<String, String>();
28972953
srpAuthResponses.put(CognitoServiceConstants.CHLG_RESP_PASSWORD_CLAIM_SECRET_BLOCK,
2898-
challenge.getChallengeParameters()
2899-
.get(CognitoServiceConstants.CHLG_PARAM_SECRET_BLOCK));
2954+
secretBlockString);
29002955
srpAuthResponses.put(CognitoServiceConstants.CHLG_RESP_PASSWORD_CLAIM_SIGNATURE,
29012956
new String(Base64.encode(hmac), StringUtils.UTF8));
29022957
srpAuthResponses.put(CognitoServiceConstants.CHLG_RESP_TIMESTAMP, dateString);
@@ -2905,9 +2960,9 @@ private RespondToAuthChallengeRequest userSrpAuthRequest(InitiateAuthResult chal
29052960
srpAuthResponses.put(CognitoServiceConstants.CHLG_RESP_SECRET_HASH, secretHash);
29062961

29072962
final RespondToAuthChallengeRequest authChallengeRequest = new RespondToAuthChallengeRequest();
2908-
authChallengeRequest.setChallengeName(challenge.getChallengeName());
2963+
authChallengeRequest.setChallengeName(challengeName);
29092964
authChallengeRequest.setClientId(clientId);
2910-
authChallengeRequest.setSession(challenge.getSession());
2965+
authChallengeRequest.setSession(session);
29112966
authChallengeRequest.setChallengeResponses(srpAuthResponses);
29122967
final String pinpointEndpointId = pool.getPinpointEndpointId();
29132968
if (pinpointEndpointId != null) {

0 commit comments

Comments
 (0)