[NodeJS] Call Function to Authneticate, Got Promise Back

Hi folks,
I have a little problem that I try to solve. In Node I create an API. To call it I let the user also submit an authentication code/token that needs to be verified before proceeding with the request.
Now let’s say I call a function “user”, in this function I call a function auth in another file. The token is there, but first I get back a Promise { false }.

I better show the code:

Here’s the one I call via the API:

let findUserByEmail = (req,res) => {
    let token = req.headers['authorization'];
    
    if(!token){
        console.log("error "+token)
    }
    else if(token){
        var auth_status = auth.auth(token);
        console.log("next: auth status")
        console.log(auth_status)
        if(!auth_status){
            console.log("no auth "+auth_status)
        }
        console.log("the status is")
        console.log(auth_status)        
    }    
    con.query('SELECT * FROM users WHERE user_id = ?',[req.params.id], function (error, results, fields) {
        try{
          respo["data"] = results;
          respo["value"] = auth_status;
          //console.log(respo)
          res.send(respo)
        }catch(err){
          console.log("oh oh")
        }
    });

    //res.send(results);
    
};

The auth-function I am calling in the auth-file is:

async function auth(token) {
    console.log("auth")
    let status = false;
    if(token){
        console.log("true "+token)
        //let token =  token;
        con.query('SELECT token,user_id FROM users_token WHERE token = ?',[token],function(error,results,field){
            try{
                console.log("true after try "+results[0]["user_id"])
                status = results[0]["user_id"];
            }catch(err){
                console.log("false after try")
                status = false;
            }            
        })
    }
    else {
        console.log("false")
        status = false;
    }
    console.log("see status in auth")
    console.log(status)
    return status;
};

As you can see I work with many console-logs, but this helped me to see what is happening.

auth
true token123
see status in auth
false
next: auth status
Promise { false }
the status is
Promise { false }
true after try 1

So I get back a Promise with false two times rather than a right result. In the end I get the API returning the data I want, but it feels like Auth is not working correctly. How can I fix this and understand the issue?

Hi @nucky, I fear you are returning before your async action completes:

 if(token){
        // you enter this block
      // I assume the below function is an asynchronous task. It will return probably sometimes later
        con.query( <...>)
    }
    else {
    }

  // your async action is performing in the background, but the function is still executing
// so I will be evaluated as well.
    console.log("see status in auth")
    console.log(status)
    return status;

Remember that Node engine is synchronous, so you probably want to restructure how you consume your API.

// this is an asynchronous operation
var auth_status = auth.auth(token);

Hope this helps seeing the issue :sparkles:

Hi Marmiz, thank you for your feedback. Yeah, I am quite new to Node, did React before. I may not get your reply completely. How could this be solved? Because calling auth.auth(token) wouldn’t work as I get the token from the request inside a function.

I see here you are using async/await, are you familiar with it?
That can help you simplify your code so it “look” synchronous yet still behave asynchronously.

async/await is sintactic sugar for Promises, are you comfortable with them?

I see you are making an SQL query with

con.query

But what package is that? What is returning?
If you have the option of using Promises instead of callback I’d go for it.

But I don’t have enough intel to give you all the answer.

Okay, let’s answer step by step:
The package I use is "mysql": "^2.18.1". And con.query refers to con or const con = require("../config/DBConnections");, so it’s what I need toconnect to the database.

So far, yes, familiar with Async and Await, but need to practice more. But worked with it recently.

As you propose a promise, you mean like chaining, let’s say

let findUserByEmail = (req,res) => {
    let token = req.headers['authorization'];
    
    if(!token){
        console.log("error "+token)
    }
    else if(token){
auth.auth(token).then(result => auth_status = result).then(on.query('SELECT ...)

?

I try around and don’t find a solution. Generally, when I start the request, the Auth checks if a token is valid and if it is, I’d return the user_id, else return false. So I can use the user_id in the queries.

As far as I can see the problem is in auth as it requires two, three processes to get the result.

After a quick glance to mysql docs I saw there’s no method that return Promises, which is a bit of a bummer to me.

You either wrap them into a promise yourself:

function doQuery(...whatever) {
  return new Promise((resolve, reject) => {
    con.query([...], () => { resolve(data) })
})
}

So that at least you could:

async function auth(token) { 
  let data = await doQuery(....);
 // do whatever
}
let findUserByEmail = async (req,res) => {
    let token = req.headers['authorization'];
    
    if(!token){
        console.log("error "+token)
    }
    else if(token){
        var auth_status = await auth.auth(token);
[...rest]

Otherwise you have to stay with the current callback configuration, so you probably want to pass a callback to auth function to execute whatever logic after is done.

Welcome to the infamous node callback hell :smiley:

Have solved the issue. :slight_smile:
I did as follow. In the auth-file I export functions “inline”.

module.exports = {
  tokenauth: async function(token) {..etc}
}

and in my main-file I use another structure like this:

let getKitten = async (req, res) => {
     let token = auth.tokenauth(token)
}

module.exports = { getKitten, ...}

And it works fine. :slight_smile: Marmiz, I am thankful for your help.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.