Página 1 de 1

ReCAPTCHA v2

Publicado: Jue Feb 04, 2021 8:10 pm
por ricardo arraes
Hey everybody!

Here once again to talk about web application security, this time Imma talk about a pretty simple feature that is extremely useful, specially when it's related to authentication.

reCAPTCHA is a Google API made to identify human interaction over a application.
There are some versions of reCAPTCHA available, in this example I'll explain how to use the v2, probably the most common (v1 is deprecated).

*the reCAPTCHA v3 requires no user interaction (trying to avoid user friction). I'll talk about it later...

the reCAPTCHA v2 has some options, you can choose:

- "I'm not a robot" checkbox
- background validation (requires no user interaction, similar to reCAPTCHA v3)
- validation through Android App

for this example, I chose the "I'm not a robot" checkbox, which is the most used and we're all familiar with it...

first of all, you have to go to the reCAPTCHA admin console and create the keys for your website/web application

https://www.google.com/recaptcha/about/

one of these keys is the secret key (you must keep it in secret, obviously). and the other key is a public key, which you will attach at your HTML elements (I'll show you later how to do it).

In my example I did this:

1. created an environment variable in my .htaccess in order to keep the secret key:

Código: Seleccionar todo

SetEnv SECCAP		   "6LcVSDKIJFOSFDF8S9ZXXdswedy6C8llVRSxmRuK5s_I6"
2. added the script to "download" the reCAPTCHA API js in my view (HTML):
*Add this line in the HEAD of your HTML document (View).

Código: Seleccionar todo

<head>
      ...
      <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    ...
</head>
3. create a <div> element in my HTML document (view) which will render the reCAPTCHA widget:
*the attribute "data-sitekey" must contain your PUBLIC KEY created in you reCAPTCHA admin console

Código: Seleccionar todo

<form class="form-signin" id="demo-form"  action="{{ Route( 'login' ) }}" method="post" >        
             <input type="text"  name="user" id="user"  class="form-control" placeholder="User" required>
            <input type="password" name="psw" id="psw" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" class="form-control mt-2" placeholder="Password" required>=
            <div class="g-recaptcha mt-2" data-sitekey="6LcVR9cZAFHISDFHSEIORDSCYkN9jEy2gw_SzR2nA9d"></div>

        <button class="btn btn-lg btn-primary btn-block" type="submit" style="background-color: olivedrab;margin-top: 1rem">Login</button>
    </form>
4. create another script at the end of my HTML document, in order to detect if reCAPTCHA is checked or not

Código: Seleccionar todo

<script>
    document.getElementById("demo-form").addEventListener("submit",function(evt)
    {
    
      var response = grecaptcha.getResponse();
      if(response.length == 0) 
      { 
        alert("Please, confirm that you are not a robot!"); 
        evt.preventDefault();
        return false;
      }
    
    });    
  </script>
5. our form is sending a post method to a route of our application, inside this route I gotta make some validations as well.
*checking the "I'm not a robot" checkbox is not enough, you must send a HTTP request to a Google URL which is going to verify your keys and the recaptcha code generated at the moment you checked the box.

*we are going to use CURL to send the request to the google URL

Código: Seleccionar todo

LOCAL cRecaptcha, hCurl, hRecaptchaResponse:={=>}

cRecaptcha      := oController:oRequest:Post('g-recaptcha-response')

IF cRecaptcha = NIL .OR. Empty(cRecaptcha)
        oController:View( "login.view")    
        return nil
ENDIF    

curl_global_init()

IF ! empty( hCurl := curl_easy_init() )
    
      curl_easy_setopt(hCurl,HB_CURLOPT_CUSTOMREQUEST,"POST")
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify?"+"secret="+AP_GetEnv("SECCAP")+"&"+"response="+cRecaptcha )  
      curl_easy_setopt(hCurl, HB_CURLOPT_FOLLOWLOCATION, 1)
      curl_easy_setopt(hCurl, HB_CURLOPT_SSL_VERIFYPEER, 0)
      //curl_easy_setopt( hCurl, HB_CURLOPT_USE_SSL, 1 )
      
      curl_easy_setopt( hCurl, HB_CURLOPT_HTTPHEADER, NIL )
      curl_easy_setopt(hCurl, HB_CURLOPT_POSTFIELDS, "")        
      
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_BUFF_SETUP )
      
      IF (nret:=curl_easy_perform( hCurl )) == 0
        uValue := curl_easy_dl_buff_get( hCurl )
        hRecaptchaResponse:=hb_jsonDecode(uValue)  

        IF hRecaptchaResponse=NIL .OR. .NOT. hRecaptchaResponse['success']
          curl_global_cleanup()   
          RETURN NIL
        ENDIF
      ELSE
        curl_global_cleanup()   
        RETURN NIL
      ENDIF

     curl_global_cleanup()   

ENDIF
and that's it! if hRecaptchaResponse is true, the reCAPTCHA validation went well and your keys are authenticated by google.

Hope it helps you!

Re: ReCAPTCHA v2

Publicado: Vie Feb 05, 2021 1:58 am
por Cristobal
Muy interesante, gracias

Re: ReCAPTCHA v2

Publicado: Vie Feb 05, 2021 5:18 am
por ramirezosvaldo
Gracias Ricardo
Excelente!!!
Saludos

Re: ReCAPTCHA v2

Publicado: Lun Feb 08, 2021 3:30 am
por ralph
Gracias, muy util tu aporte!