I am relatively new to Javascript so please bear with me. I have googled and tested for a day with no success so I need to ask the community for some help. I am trying to verify the content of a contact form on my React JS website using Recaptcha3. I receive the token based on the content of the form (email, name) seemingly correctly, but sending the token to my backend (Firebase functions) does not work. I keep getting crash with:
....
2021-08-25T03:45:00.892Z I sendRecaptcha: token undefined
2021-08-25T03:45:01.198Z ? sendRecaptcha: { success: false, error: 'response not valid' }
2021-08-25T03:45:01.199Z ? sendRecaptcha: Unhandled rejection
2021-08-25T03:45:01.246Z ? sendRecaptcha: { success: false, error: 'captcha_error' }
2021-08-25T03:45:01.252056348Z D sendRecaptcha: Function execution took 374 ms, finished with status: 'crash'
My code after pressing submit on the form triggers a cloud function sendRecaptcha
:
const handleSubmit = event => {
event.preventDefault()
const apiString = 'https://xxxx.cloudfunctions.net/sendRecaptcha'
setLoading(true);
window.grecaptcha.ready(() => {
window.grecaptcha.execute(SITE_KEY, {action: 'form'})
.then(function(token) {
console.log("TOKEN: ",token);
Axios.get(`${apiString}?token=${token}`)
.then(function (response) {
const score = response.data.score;
console.log("score: ", score);
sendVerifiedContent()
$("#contact").unbind('submit').submit();
})
.catch(function (error) {
console.log("error: ", error);
});
});
});
}
My index.js cloud function ( Firebase function):
const USER_ERROR_CODES = ['missing-input-response', 'invalid-input-response']
exports.sendRecaptcha = functions.https.onRequest(async (req, res) => {
//res.set('Access-Control-Allow-Origin', functions.config().recaptcha.origin);
res.set('Access-Control-Allow-Origin', '*')
res.set('Access-Control-Allow-Methods', 'GET, PUT, POST, OPTIONS')
res.set('Access-Control-Allow-Headers', '*')
const secret = functions.config().recaptacha.key;
functions.logger.log("SECRET:", secret);
const token = res.query.body;
functions.logger.log("token", token);
try {
let result = await axios({
method: 'post',
url: 'https://www.google.com/recaptcha/api/siteverify',
params: {
secret:secret,
response:token,
}
});
let data = result.data || {};
if(!data.success){
throw({
success: false,
error: 'response not valid'
})
}
}catch(err){
console.log(err);
throw err.response ? err.response.data : {success: false, error: 'captcha_error'}
}
})
When window.grecaptcha.execute
function finishes I see the token and it looks something like this (seemingly OK):
03AGdBq255ghLC0DOUleaz71srZlcYWCiVlR-aldGXQZ6L2D-wIkJb5V_NDh66AYWsERT0w9hFLIt5nVikfjigufJvA2phS_ns-6X8YAza0S-nCS0RUPx1IgJBQUZ1Vl-Cc5AfuOcavSzCicNtSHAcLLXZPY-dY3PbIo-jzelpBelyfD8RGB8dKrWreP2cCfgitjs24xtX8J94ED3WC4DzQKCbfvEEQrEoAHWY2rueU2lDfflBybpz5u7lXccd_zDTORy9WEiHQBK2vEuEuJXZ-85mLP1acI03I1lOXpm_uLBTO3YJMpXc5Jq-4eRO4vDvox23YxfKYgXQd5UZPvkWQWq7sv_9ANUZK1w28LeK7aZO-9KUmGMmm3IFfaOKYrggVAIoEq8ex3unGZTxwq4ZnrYzYhGAx02PAmC5UQEjbBHLDStfYaaLHh8
But once my cloud function is called I am unable to get the token from the req.query.token
(the output of functions.logger.log("token", token)
is undefined) and the rest of the function crashes.
I am certain it`s a beginner problem here but would love some help.
Update I followed the suggestion from @Dharmaraj and I am able to get the token correctly in my cloud function. The function seems stuck though and times out. Is there anything else that may be up for improvements in my code?
D sendRecaptcha: Function execution took 60011 ms, finished with status: 'timeout'
The query
property exists on request
object and not response
. To access query parameters, refactor your code to this:
const token = req.query.token;
// alternatively using object destructuring
const {token} = req.query
req.query
will be an object of all the query parameters. For example, if your URL is https://domain.tld?q1=hello&q2=world
, req.query
will be {q1: "hello", q2: "world"}
You should terminate your HTTP functions by sending a response else it'll keep running for 60 seconds (or your max timeout duration) and eventually end with that timeout error:
try {
if (!data.success) {
throw ({
success: false,
error: 'response not valid'
})
}
res.status(200).json({data: data})
} catch (e) {
console.log(e)
res.status(500).json({error: e})
}
From the documentation,
Make sure that all HTTP functions terminate properly. By terminating functions correctly, you can avoid excessive charges from functions that run for too long. Terminate HTTP functions with res.redirect(), res.send(), or res.end().