Search code examples
javascriptjquerynode.jsfirebaserecaptcha

SyntaxError: Unexpected token u in JSON at position 0 at JSON.parse (<anonymous>)


I have added reCaptcha to my firebase project. Using send button I am sending form data as well as the response from captcha using grecaptcha.getResponse() to my server.

here is client.js code:

$('.sendUrl').on('click', function(e){
      e.preventDefault() ;
      
      $('#nonauthForm').validate({
         rules: {
            url_nauth: {
               required: true,
               url: true
            }
         }
      }) ;
      
      if( $('#nonauthForm').valid()){
         var captcha_val = grecaptcha.getResponse(widget1) ;
         
         $.post('/nonauth_url',{
            URL: $('#url').val(),
            CAPTCHA: captcha_val
         },function(data, status){
            if(status === 'success'){
               if(data.val === 1){
                  $('#newurl').html(`${window.location.origin+ '/'+ data.code}`) ;
                  $('#url').val('') ;
                  grecaptcha.reset(widget1) ;
               }
               else if( data.val === 0 ){
                  alert('Please select the captcha to continue !!') ;
               }
               else if( data.val === -1){
                  alert('Failed to verify captcha !!') ;
                  grecaptcha.reset(widget1) ;
               }
            }
         }).fail(function(res){
            errorAlert('Error occurred', 'An error happend while connecting to the server !') ;
         }) ;
      }
      else{
         $('label.error').addClass('text-danger d-block mt-2');
      }
      
   }) ;

here is my node server code (index.js):

const express = require('express') ;
const urlId = require('shortid') ;
const string = require('randomstring') ;
const app = express() ;
require('dotenv').config() ;
const secretkey = process.env.SECRETKEY ;

app.post('/nonauth_url', (req, res) => {
   let captchaRes = req.body.CAPTCHA ;
   if(captchaRes === undefined || captchaRes === '' || captchaRes === null) {
      return res.send({
         val: 0 ,
         code: null
      }) ;
   }
   let verification_url = `https://www.google.com/recaptcha/api/siteverify?secret=${secretkey}&response=${captchaRes}&remoteip=${req.connection.remoteAddress}` ;
   
   request(verification_url, function(err,response,body){
      let data = JSON.parse(body) ;
      if( data.success !== undefined && !data.success){
         return res.send({
            val: -1,
            code: null
         }) ;
      }
      
      let codeGenerated = 'n' + urlId.generate() ; // n for non-authenticated users
      
      let docname = 'doc-' + string.generate(4) ;
      
      let schema = {
         code: codeGenerated,
         url: req.body.URL,
         expiredAt: Date.now()+600000  // in milisceonds for 10min
      }
      
      let docRef = db.collection('nonauth_url').doc(docname).set(schema).then(() => {
         res.send({
            val: 1,
            code: schema.code
         }) ;
      }).catch(err => {
         console.log(err) ;
      }) ;
   }) ;
}) ;

exports.routeFunc = functions.https.onRequest(app) ;

So, with this if user doesn't check the captcha its will return code 0, code 1 for success & code -1 for failure in verification. This code is working perfectly on localhost. But on my hosting url **.firebaseapp.com if I'm not checking the captcha it's responding back for requirement of the captcha. But when I'm checking the recaptcha and sending the request to the server it's giving an error code of 500.

This is console for my functions in my main project console: enter image description here

EDIT: Now I've used axios instead of request

New code:

axios.get(verification_url).then( res => {
      return res.data ;
   }).then( object => {
      if(object.success){
         let codeGenerated = 'n' + urlId.generate() ; // n for non-authenticated users
         
         let docname = 'doc-' + string.generate(4) ;
         
         let schema = {
            code: codeGenerated,
            url: req.body.URL,
            expiredAt: Date.now()+600000  // in milisceonds for 10min
         }
         
         let docRef = db.collection('nonauth_url').doc(docname).set(schema).then(() => {
            res.send({
               val: 1,
               code: schema.code
            }) ;
         }).catch(err => {
            console.log(err) ;
         }) ;
      }
      else{
         res.send({
            val: -1,
            code: null
         }) ;
      }
   }).catch(err => {
      console.log("Error occurred in axios",err) ;
   }) ;
}) ;

Now its giving following error: Error occurred in axios

{ Error: getaddrinfo EAI_AGAIN www.google.com:443 at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:67:26) errno: 'EAI_AGAIN', code: 'EAI_AGAIN', syscall: 'getaddrinfo', hostname: 'www.google.com', host: 'www.google.com', port: 443 . . . . }


Solution

  • So, I was able to solve this issue by changing the verfication url i.e www.google.com/recaptcha/api/siteverify which is not meant for firebase project only for node.js on checking reCaptcha for firebase link here


    Also changing my previous answer to this one:

    const rp = require('request-promise') ;
    rp({
          uri: 'https://recaptcha.google.com/recaptcha/api/siteverify',
          method: 'POST',
          formData: {
             secret: secretkey,
             response: captchaRes
          },
          json: true
       }).then(result => {
          console.log("recaptcha result", result)
          if (result.success) {
             // for human detection
          }
          else {
             // for bot detection
          }
       }).catch(reason => {
          // error handling
    }) ;

    and deploying it on the firebase it finally worked. I think firebase was not allowing to make call to the older recaptcha verfication address for which I needed a paid plan but on searching for firebase with recaptcha solved my issue.