Why am I getting the response "SecretHash does not match for the client" during AWS Congito User confirmation?

308 Views Asked by At

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:

  1. I'm using the following Authentication flows:
  • ALLOW_REFRESH_TOKEN_AUTH
  • ALLOW_USER_PASSWORD_AUTH
  1. 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)",

1

There are 1 best solutions below

0
WDE On

I tried a few different things but eventually realized that I had some trailing whitespace where I was setting the environment variables in my lambda. I cleaned that up and it was working.