0
votes

I'm making a web app with react. For the authentication I'm using firebase auth, and for the data storage I have an express backend with postgresql.

At the moment for retrieve the user data from my backend I'm sending the idToken of the current user (provided from firebase). Then in my backend, I verify the idToken with firebase sdk. Is this enough secure?

In future I'm going to add the payments functions. Is it secure enough to validate the user that is paying using the firebase idToken and then accept the payment?

I'm absolutely beginner in security!

This is how I get/update and create a new user:

   const getUserById = (request, response) => { //Dammi l'utente con il tokenID passato
    const idToken = request.params.idToken
    utils.firebase.auth().verifyIdToken(idToken)
      .then(function(decodedToken){
        let uid = decodedToken.uid

        utils.pool.query('SELECT * FROM users WHERE uid = $1', [uid], (error, results) => {
          if (error) {
            throw error
          }
          response.status(200).json(results.rows)
        })
      }).catch(function(error) {
        // Handle error
      });
  }



const createUser = (request, response) => { //Crea nuovo user
    const { idToken, fullname} = request.body

      utils.firebase.auth().verifyIdToken(idToken) //Verifico il token utente in ingresso
        .then(function(decodedToken) { //se è verificato allora estraggo l'uid
          let uid = decodedToken.uid;
          console.log("Registered new User, UID: " + uid)
          console.log("name: " + fullname)
          utils.pool.query('INSERT INTO users (uid,fullname) VALUES ($1, $2)', [uid, fullname], (error, results) => {
            if (error) {
              throw error
            }
            response.status(201).send(`User added with ID: ${results}`)
          })
        }).catch(function(error) {
          // Handle error
        });
  }


  const updateUser = (request, response) => { //Aggiorna le info dell'utente, nome e biografia, l'email verrà gestita da firebase
    const idToken = request.params.idToken
    const { fullname, bio } = request.body

    utils.firebase.auth().verifyIdToken(idToken) //verifico che il token sia vero
    .then(function(decodedToken){
      let uid = decodedToken.uid //estrapolo lo uid dell'utente
      console.log("Edited the user: " + uid)
      console.log("Name: " + fullname)


      utils.pool.query(
        'UPDATE users SET fullname = $1, bio = $2 WHERE uid = $3', [fullname, bio, uid], (error, results) => {
          if (error) {
            throw error
          }
          response.status(200).send(`User modified with ID: ${results}`)
        }
      )
    })
  }

Can anyone explain me if there are security problems?? And the minimum security rules for push a webapp + nodejs in production securely?

1

1 Answers

0
votes

From quickly scanning your code, the getUserById looks correct to me. The crucial steps you take:

  1. You verify that the ID token is valid.

    Since the token is signed with the public key of your project on the client, which only you can decode with the same project credentials on the server, this ensures users can't send you just any old value.

  2. You then use the UID from this ID token retrieve the data for that user from the database.

    This step of course depends on what you actually want to allow in your application, but at first glance this looks normal. It's the equivalent of a check like this in Firestore security rules: request.auth.uid == resource.data.uid.

Your createUser method looks similar enough in how it handles the ID token. The only thing I'd flag there is that you're taking fullname from the request body, which means the user can pass whatever value they want in there. If that is exactly what you want, then the code does what you want. But if you're trying to get the user's display name, you might want to get that from their ID token too, just like you do with the UID.