2

I can't enable CORS in GCF, allUsers is enabled. Here's my code following this post recommandations

I make a POST call with fetch and JSON as body. My server supposed to handle the request by performing a reCaptcha verification. Then respond based on the reCaptcha score.

Thing is I can't even make the request, my server returns status 500. Emails are sent when sent with 'mode : no-cors'.

exports.contactSendmail = (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');

  if (req.method === 'OPTIONS') {
    /* handle preflight OPTIONS request */

    res.set('Access-Control-Allow-Methods', 'GET, POST');
    res.set('Access-Control-Allow-Headers', 'Content-Type, Accept');

    // cache preflight response for 3600 sec
    res.set('Access-Control-Max-Age', '3600');

    return res.status(204);
  }

  const { message, token, email } = JSON.parse(req.body);
  console.log(message, token, email);

  // Load Node native HTTPS package
  const https = require('https');
  const sgMail = require('@sendgrid/mail');
  sgMail.setApiKey(process.env.SENDGRID_API_KEY);
  const recapatchaKeys = {
    secret: `myhiddensecretkey`,
    response: token,
  };
  const urlPath = `/recaptcha/api/siteverify?secret=${recapatchaKeys.secret}&response=${recapatchaKeys.response}`;
  const recaptchaOptions = {
    hostname: 'google.com',
    // port: 443,
    path: urlPath,
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Content-Length': 0,
    },
  };
  const reqRecaptcha = https.request(recaptchaOptions, (recaptchaResponse) => {
    console.log(`reCaptcha statusCode: ${recaptchaResponse.statusCode}`);
    recaptchaResponse.on('data', (d) => {
      process.stdout.write(d);
      const recapatchaRes = JSON.parse(d);
      if (recapatchaRes.score > 0.7) {
        const msg = {
          to: process.env.CONTACT_EMAIL_RECIPIENT,
          from: email,
          subject: 'Nouveau contact',
          text: message,
          // html: "<strong>Its too simple to send mail</strong>"
        };
        //ES8
        (async () => {
          try {
            await sgMail.send(msg);
            res.status(200).send('Email sent');
            console.log('Email sent !');
          } catch (err) {
            console.error('Error with Sendgrid' + err.toString());
          }
        })();
      } else {
        res.status(403).send('Forbidden to send Email');
        console.log('Forbidden to send Email');
      }
    });
  });
  reqRecaptcha.write('');
  reqRecaptcha.end();
};

Here's my front call

const response = await fetch(process.env.CONTACT_SENDMAIL_URL, {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(emailBody),
});

Any help would be appreciated

felixmosh
  • 32,615
  • 9
  • 69
  • 88
  • You are not handling any authentication in there, the [Docs](https://cloud.google.com/functions/docs/writing/http#limitations) state that if you enable `allUsers`, you should handle authentication as well as CORS (which you are doing) in the function to make it work. Alternatively you could try deploying it with `--allow-unauthenticated`, is this possible in your project? – Ralemos Mar 23 '21 at 13:18
  • I've deployed my function with "Allow unauthenticated" ( => https://prnt.sc/10ubr02) . Indeed the docs states "Then handle CORS and authentication IN THE FUNCTION CODE", but how can I handle auth in the code ? – Philippe Braun Mar 24 '21 at 14:36
  • You can follow the instructions [here](https://cloud.google.com/functions/docs/securing/authenticating#end-users) for that. – Ralemos Mar 30 '21 at 13:29

1 Answers1

1

As mentioned in the comments, you are not handling any authentication in there. The Documentation states that:

you can either deploy it with the --allow-unauthenticated flag, or use the Console to grant the Cloud Functions Invoker role to allUsers. Then handle CORS and authentication in the function code.

And in order to handle authentication for end users you can in your code you can follow the instruction in this other piece of documentation, which is quite detailed.

Ralemos
  • 5,571
  • 2
  • 9
  • 18
  • @WytrzymałyWiktor I could use a little help... I need to send request from my app with token in the Bearer ? I don't get what [this code](https://cloud.google.com/functions/docs/securing/authenticating#generating_tokens_programmatically) is doing or should be implemented – Philippe Braun Jun 03 '21 at 16:04