ReCAPTCHA v2

Responder
Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 3 years 5 months
Brazil

ReCAPTCHA v2

Mensaje 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!
The work always comes before the belief

Cristobal
Site Admin
Mensajes: 315
Registered for: 3 years 6 months
Spain

Mensaje por Cristobal »

Muy interesante, gracias
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces

ramirezosvaldo
Mensajes: 127
Registered for: 3 years 5 months
Mexico

Mensaje por ramirezosvaldo »

Gracias Ricardo
Excelente!!!
Saludos

ralph
Mensajes: 7
Registered for: 3 years 5 months
Peru

Mensaje por ralph »

Gracias, muy util tu aporte!

Responder