I'm getting the following response during user confirmation with AWS Cognito:
{
"errorMessage": "SecretHash does not match for the client: [REDACTED] (Service: AWSCognitoIdentityProvider; Status Code: 400; Error Code: NotAuthorizedException; Request ID: [REDACTED]; Proxy: null)",
"errorType": "com.amazonaws.services.cognitoidp.model.NotAuthorizedException",
"stackTrace": [
"com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1811)",
"com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1395)",
"com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1371)",
"com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1145)",
"com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:802)",
...
I'm using the implementation recommended by AWS for user signup:
public static void signUp(CognitoIdentityProviderClient identityProviderClient, String clientId, String userName, String password, String email) {
AttributeType userAttrs = AttributeType.builder()
.name("email")
.value(email)
.build();
List<AttributeType> userAttrsList = new ArrayList<>();
userAttrsList.add(userAttrs);
try {
SignUpRequest signUpRequest = SignUpRequest.builder()
.userAttributes(userAttrsList)
.username(userName)
.clientId(clientId)
.password(password)
.withSecretHash(calculateSecretHash(clientId, USER_POOL_CLIENT_SECRET, userName))
.build();
identityProviderClient.signUp(signUpRequest);
System.out.println("User has been signed up ");
} catch(CognitoIdentityProviderException e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
I'm using the implementation recommended by AWS for user confirmation (with the withSecretHash() method added):
public static void confirmSignUp(CognitoIdentityProviderClient identityProviderClient, String clientId, String code, String userName) {
try {
ConfirmSignUpRequest signUpRequest = ConfirmSignUpRequest.builder()
.clientId(clientId)
.confirmationCode(code)
.username(userName)
.withSecretHash(calculateSecretHash(clientId, USER_POOL_CLIENT_SECRET, userName))
.build();
identityProviderClient.confirmSignUp(signUpRequest);
System.out.println(userName + " was confirmed");
} catch(CognitoIdentityProviderException e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
I'm using the implementation recommended by AWS for calculating the hash:
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public static String calculateSecretHash(String userPoolClientId, String userPoolClientSecret, String userName) {
final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
SecretKeySpec signingKey = new SecretKeySpec(
userPoolClientSecret.getBytes(StandardCharsets.UTF_8),
HMAC_SHA256_ALGORITHM);
try {
Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
mac.init(signingKey);
mac.update(userName.getBytes(StandardCharsets.UTF_8));
byte[] rawHmac = mac.doFinal(userPoolClientId.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(rawHmac);
} catch (Exception e) {
throw new RuntimeException("Error while calculating ");
}
}
Additional points which I don't know that matter or not:
- I'm using the following Authentication flows:
- ALLOW_REFRESH_TOKEN_AUTH
- ALLOW_USER_PASSWORD_AUTH
- I'm using the correct username and confirmation code sent via email.
Can anyone point out where I may be going wrong? Thanks in advance!
Tried to sign a user up and confirm them using the Java AWS SDK. Expected to be able to sign them up and confirm them. Resulted in error: "errorMessage": "SecretHash does not match for the client: [REDACTED] (Service: AWSCognitoIdentityProvider; Status Code: 400; Error Code: NotAuthorizedException; Request ID: [REDACTED]; Proxy: null)",