Victor Manuel
Victor Manuel

Reputation: 61

firebase function returns 403 when doing an http request

I started working on this node.js app using express to send sensor data via http request to my database (from an arduino to be specific). The main purpose of the app is to get the sensors' values from the url and create a new document in my cloud firestore.

var admin = require('firebase-admin');
const functions = require('firebase-functions');
const cors = require('cors')({origin: true});
const express = require('express');
var serviceAccount = require("./minicapcollar-firebase-adminsdk-ovdpm-cda3767493.json");

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://minicapcollar.firebaseio.com"
});

let db = admin.firestore();

const app = express();
app.use(cors);

//Declare the field view for the timestamp
let FieldValue = require('firebase-admin').firestore.FieldValue;

app.get('/send/sensorData', (req, res) => {
    var id = 'HpwWiJSGHNbOgJtYi2jM'; //variable to store the id of the collar, TODO: req.query.id
    var lat = req.query.lat/1000000;
    var lon = req.query.lon/1000000;
    var hr = req.query.hr;
    var et = req.query.et;
    var it = req.query.it;
    //Rest of the values

    //Declare the index of the collar id
    let indexRef = db.collection('dogs').doc(id);

    //Declare the index of the position
    let posRef = indexRef.collection('position').doc();

    //Declare the index of the heartrate
    let hrRef = indexRef.collection('heartrate').doc();

    //Declare the index of the external temperature
    let etRef = indexRef.collection('external_temperature').doc();

    //Declare the index of the internal temperature
    let itRef = indexRef.collection('temperature').doc();

    //Save the current time
    var time = FieldValue.serverTimestamp();

    //Set position
    let setPos = posRef.set({
        timestamp: time,
        value: new admin.firestore.GeoPoint(lat,lon)
    }).then(function() {
        console.log("Position data saved to Firestore");
        return null;
    }).catch(function(error) {
        console.log("Got an error: ", error);
    });

    //Set heartrate
    let setHr = hrRef.set({
        timestamp: time,
        value: hr
    }).then(function() {
        console.log("Heartrate data saved to Firestore");
        return null;
    }).catch(function(error) {
        console.log("Got an error: ", error);
    });

    //Set external temperature
    let setET = etRef.set({
        timestamp: time,
        value: et
    }).then(function() {
        console.log("External temperature data saved to Firestore");
        return null;
    }).catch(function(error) {
        console.log("Got an error: ", error);
    });

    //Set internal temperature
    let setIT = itRef.set({
        timestamp: time,
        value: it
    }).then(function() {
        console.log("Data saved to Firestore");
        return null;
    }).catch(function(error) {
        console.log("Got an error: ", error);
    });


    res.send(`All sensor data sent`);


});

app.get('/send/pos', (req, res) => {
    var id = 'HpwWiJSGHNbOgJtYi2jM'; //variable to store the id of the collar, TODO: req.query.id
    var lat = req.query.lat/1000000;
    var lon = req.query.lon/1000000;
    //Rest of the values

    //Declare the index of the collar id
    let indexRef = db.collection('dogs').doc(id);

    //Declare the index of the position
    let posRef = indexRef.collection('position').doc();

    //Save the current time
    var time = FieldValue.serverTimestamp();

    //Set position
    let setPos = posRef.set({
        timestamp: time,
        value: new admin.firestore.GeoPoint(lat,lon)
    }).then(function() {
        console.log("Position data saved to Firestore");
        return null;
    }).catch(function(error) {
        console.log("Got an error: ", error);
    });

    res.send(`Position sent`);
});

app.get('/send/hr', (req, res) => {
    var id = 'HpwWiJSGHNbOgJtYi2jM'; //variable to store the id of the collar, TODO: req.query.id
    var hr = req.query.hr;

    //Declare the index of the collar id
    let indexRef = db.collection('dogs').doc(id);

    //Declare the index of the heartrate
    let hrRef = indexRef.collection('heartrate').doc();

    //Save the current time
    var time = FieldValue.serverTimestamp();

    //Set heartrate
    let setHr = hrRef.set({
        timestamp: time,
        value: hr
    }).then(function() {
        console.log("Heartrate data saved to Firestore");
        return null;
    }).catch(function(error) {
        console.log("Got an error: ", error);
    });

    res.send(setHr & `Heartrate value sent`);
});

app.get('/send/temp', (req, res) => {
    var id = 'HpwWiJSGHNbOgJtYi2jM'; //variable to store the id of the collar, TODO: req.query.id
    var et = req.query.et;
    var it = req.query.it;

    //Declare the index of the collar id
    let indexRef = db.collection('dogs').doc(id);

    //Declare the index of the external temperature
    let etRef = indexRef.collection('external_temperature').doc();

    //Declare the index of the internal temperature
    let itRef = indexRef.collection('temperature').doc();

    //Save the current time
    var time = FieldValue.serverTimestamp();

    //Set external temperature
    let setET = etRef.set({
        timestamp: time,
        value: et
    }).then(function() {
        console.log("External temperature data saved to Firestore");
        return null;
    }).catch(function(error) {
        console.log("Got an error: ", error);
    });

    //Set internal temperature
    let setIT = itRef.set({
        timestamp: time,
        value: it
    }).then(function() {
        console.log("Data saved to Firestore");
        return null;
    }).catch(function(error) {
        console.log("Got an error: ", error);
    });

    res.send(`Temperature values sent`);
});

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

Once I finished the app, I tested it on my localhost, and it worked perfectly. I was able to write new data to the cloud firestore without any problems. Once I deployed my app, when sending the request, I get a 403 (Error: Forbidden Your client does not have permission to get URL /app/send/pos/?lat=11111111&lon=22222222 from this server.)

On the firestore rules, I specified that anyone can read and write to see if that was the problem, but it persists.

I also tried to follow along this tutorial: https://www.youtube.com/watch?v=LOeioOKUKI8, but I had the same problem when trying to access "http://baseURL.firebaseapp.com/timestamp", I got a 403 error when deployed (on the localhost it worked perfectly too)

NOTE: This is my first experience with node.js, please forgive any bad practices. I am an electrical eng student, so programming is not my main strength. THANKS IN ADVANCE FOR YOUR HELP!

Upvotes: 0

Views: 3408

Answers (2)

d-_-b
d-_-b

Reputation: 23211

Deploying a function failed (for some strange reason, which happens time to time), and I guess it didn't update permissions.

Re-deploying succeeded but didn't update its permissions.

I had to delete the function and redeploy to fix this issue.

permissions

Upvotes: 1

Victor Manuel
Victor Manuel

Reputation: 61

Thank you samthecodingman! The answer you provided did the trick! The problem was in the IAM configuration of my function.

For those of you who don't want to jump yet to another link, I quote the answer provided by Mike Karp in the link above.

It seems to me that additional IAM functionality was added to Google Cloud Functions, and >as a result, you may have not turned on allUser access to the function (FYI this give >acess to the whole web).

  1. On the Cloud Functions homepage, highlight the Cloud Function you want to add all >>access to.
  2. Click "Show Info Panel" on the top right.
  3. Click "Add Members" and type "allUsers" then select "Cloud Function Invokers" under >>"Cloud Function" in the Role box.
  4. Click "Save"

Upvotes: 6

Related Questions