0

Whenever I try to reference the user's idToken from server side I get a message saying there is no user logged in. I've been stuck on this for a while so any help would be great

Here is the start.js file:

const cookieParser = require("cookie-parser");
const csrf = require("csurf");
const bodyParser = require("body-parser");
const path = require('path');
const express = require('express');
const admin = require("firebase-admin");
// const fbAuth = require('./routes/fbAuth');

const serviceAccount = require("./serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL:  "",
});

app.get("/view", function (req, res) {
  const sessionCookie = req.cookies.session || "";

  admin
    .auth()
    .verifySessionCookie(sessionCookie, true /** checkRevoked */)
    .then(() => {
      res.render("view.html");
    })
    .catch((error) => {
      res.redirect("/login");
    });
});
    
app.post("/sessionLogin", (req, res) => {
  
  const idToken = req.body.idToken.toString();

  const expiresIn = 60 * 60 * 24 * 5 * 1000;

  admin
    .auth()
    .createSessionCookie(idToken, { expiresIn })
    .then(
      (sessionCookie) => {
        const options = { maxAge: expiresIn, httpOnly: true };
        res.cookie("session", sessionCookie, options);
        res.end(JSON.stringify({ status: "success" }));
      },
      (error) => {
        res.status(401).send("UNAUTHORIZED REQUEST!");
      }
    );
});


app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); });

Here is the client side login:

window.addEventListener("DOMContentLoaded", () =>
{
  const firebaseConfig = {
    config stuff goes here...
  };

  firebase.initializeApp(firebaseConfig);
  firebase.analytics();

  firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION);
  
  document
    .getElementById("login")
    .addEventListener("submit", (event) =>
    {
      event.preventDefault();
      const login = event.target.login.value;
      const password = event.target.password.value;

      firebase
        .auth()
        .signInWithEmailAndPassword(login, password)
        .then((
        {
          user
        }) =>
        {
          return user.getIdToken().then((idToken) =>
          {
            return fetch("/sessionLogin",
            {
              method: "POST",
              headers:
              {
                Accept: "application/json",
                "Content-Type": "application/json",
                "CSRF-Token": Cookies.get("XSRF-TOKEN"),
              },
              body: JSON.stringify(
              {
                idToken
              }),
            });
          });
        })
        .then(() =>
        {
          console.log(firebase.auth().currentUser);
          window.location.assign("/view");
        });
      return false;
    });
    
});

And here is where I try to reference the token in one of the routes files called oss.js (On line 9 is where the problem is identified):

            axios(config)
              .then(function(response)
              {
                response = response.data;
                console.log(response.progress, response.status);
                if (response.progress === "complete")
                {
                  if (response.status === "success")
                  {
                    console.log("JOB COMPLETE");
                    // upload to firebase here

                    
                    var user = firebase.auth().currentUser;
                    if (user)
                    {
                      admin.auth().verifyIdToken(idToken)
                      .then(function(decodedToken) {
                        var uid = decodedToken.uid;
                        console.log("uid ->", uid);
                        return uid;
                    }).catch(function(error)
                        {
                          //Handle error
                        });
                    }
                    else
                    {
                      console.log("There is no current user.");
                    }

                  }

                }

              })
              });
         
cjmc
  • 101
  • 8
  • look here, you should find what you want => [https://stackoverflow.com/a/37901056/5427820](https://stackoverflow.com/a/37901056/5427820) – Kidas Jan 25 '21 at 15:08
  • "Whenever I try to reference the user's idToken from server side I get a message" There is quite some code in your question. Can you edit the question (there's a link right under it) to include the exact error message, its stack trace, and indicate on which line that error (first) occurs? – Frank van Puffelen Jan 25 '21 at 15:56
  • Hi Frank, I've made some edits to make it easier to navigate. Thanks for the comment. – cjmc Jan 25 '21 at 16:11

1 Answers1

0

Ok this one requires a bit of wordiness but it's the answer I got with some help of course.

Firstly, in order to reference the uid from the client-side I needed to be able to store it in the browser using 'localStorage.setItem'. Once the user logged in I stored it in the client side script as the following (please note on line 12):

  firebase
    .auth()
    .signInWithEmailAndPassword(login, password)
    .then((
    {
      user
    }) =>
    {
      localStorage.setItem('uid', user.uid);
      return user.getIdToken().then((idToken) =>
      {
        localStorage.setItem('token', idToken);
        return fetch("/sessionLogin",
        {
          method: "POST",
          headers:
          {
            Accept: "application/json",
            "Content-Type": "application/json",
            "CSRF-Token": Cookies.get("XSRF-TOKEN"),
          },
          body: JSON.stringify(
          {
            idToken
          }),
        });
      });
    })

Once that was set I needed to reference it on the other pages (i'm not using any front-end framework just now), which was done using the following code that is nested in a script file within the html file. This was attached to a function that initiates a function that allows me to reference it (please note lines 11 & 12):

$('#hiddenUploadField').change(function () {
    var node = $('#appBuckets').jstree(true).get_selected(true)[0];
    var _this = this;
    if (_this.files.length == 0) return;
    var file = _this.files[0];
    switch (node.type) {
      case 'bucket':
        var formData = new FormData();
        formData.append('fileToUpload', file);
        formData.append('bucketKey', node.id);

       let uid =  localStorage.getItem('uid');
       let token = localStorage.getItem('token');

        $.ajax({
          url: `/api/forge/oss/objects?uid=${uid}&token=${token}`,
          data: formData,
          processData: false,
          contentType: false,
          type: 'POST',
          success: function (data) {
            $('#appBuckets').jstree(true).refresh_node(node);
            _this.value = '';
          }
        });
        break;
    }
  });
});

From there I was able to call the uid and token from the browser to the desired place in the backend using the following (lines 14 & 15):

router.post('/objects', multer(
{
  dest: 'uploads/'
}).single('fileToUpload'), async (req, res, next) =>
{
  fs.readFile(req.file.path, async (err, data) =>
  {
    if (err)
    {
      next(err);
    }
    try
    {
      let uid = req.query.uid;
      let token =req.query.token;

At this point I could reference the UID and token in the code above using the following:

                var user = firebase.auth();
                const customToken = admin.auth().createCustomToken(uid)
              
                firebase.auth().onAuthStateChanged(function()
                {
                  if (user)
                  {
                    admin.auth().verifyIdToken(token)
                      .then(function(decodedToken)
                      {
                        var uid = decodedToken.uid;
                        console.log("uid ->", uid);
                        return uid;
                      }).catch(function(error)
                      {
                        //Handle error
                      });
                  }
                  else
                  {
                    console.log("There is no current user.");
                  }
                });
cjmc
  • 101
  • 8