AWS-Cognito bot prevention with google reCaptcha

Viewed 2415

My problem is the POST-Request if the user is a bot or human.

It's not possible to send the request form Client-side, otherwise u will get an error on the OPTIONS request:" (response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource)", that's because the request is only possible from Server-Side.

In AWS-Cognito there is a way to use a pre authentication function to check something like that, but I couldn't find a way to get my response element into the function.

So my question is: Is there a way to implement Google recaptcha on AWS Cognito?

1 Answers

You can send this as validationData in the signup request and perform the recaptcha verify logic in a trigger SNS Lambda

Here is a snippet using the AWS Amplify library, excuse the typescript:

Client

class AuthService {
  ...

  public signUp(
    emailAddress: string,
    phoneNumber: string,
    password: string,
    recaptchaToken: string
  ): Observable<ISignUpResult> {

    const recaptchaTokenAttributeData: ICognitoUserAttributeData = {
      Name: 'recaptchaToken',
      Value: recaptchaToken
    };

    const signupParams: SignUpParams = {
      username: emailAddress,
      password,
      attributes: {
        'email': emailAddress,
        'phone_number': phoneNumber
      },
      validationData: [
        new CognitoUserAttribute(recaptchaTokenAttributeData)
      ]
    };

    return fromPromise(Auth.signUp(signupParams));
  }

  ...
}

Cognito trigger on PreSignUp SNS Lambda code

export async function validateHuman(
  event: CognitoUserPoolTriggerEvent, 
  context: Context, 
  callback: Callback
): Promise<CognitoUserPoolTriggerHandler> {

  try {
    const recaptchaToken: string = event.request.validationData.recaptchaToken;

    console.log(recaptchaToken);

    const isHuman: boolean = await googleRecaptcha.verify({response: recaptchaToken}, (error: Error) => {
      if (error) {
        console.error(error);

        return false;
      }

      return true;
    });

    if (!isHuman) {
      throw new Error('Not human');
    }

    callback(null, event);

    return;
  } catch (error) {
    console.error(error);
    callback(null, new Response(INTERNAL_SERVER_ERROR, {message: 'Something went wrong'}));

    return;
  }
}
Related