Search code examples
node.jstokenverify

Why is this verifyToken function never getting called?


Here's my auth.mjs code:

import jwt from 'jsonwebtoken'; 

export function generateToken(userInfo){
    if(!userInfo) {
        return null;
    }
    
    const payload = { username: userInfo.username, exp: Math.floor(Date.now() / 1000) + 30}; 
    const secret = Buffer.from(process.env.JWT_SECRET).toString('base64');

    return jwt.sign(payload, secret, {algorithm: 'HS512'});
    
}

export async function verifyTokens(username, token) {
    console.error("Still inside verifyTokens");
    try{
        console.error('Inside verifyToken');
        const response = await new Promise((resolve, reject) => {
            jwt.verify(token, Buffer.from(process.env.JWT_SECRET.toString('base64'), {algorithm: 'HS512'}, (err, decoded) => {
               if (err) {
                   reject (err);
               } else {
                   resolve(decoded);
               }
            })
        )})
        
            if (response.username !== username) {
                console.error('response.username !== username');
                return {
                    verified: false,
                    message: 'invalid user'
                }
            }
            
            console.error('response.username === username');
            
            return {
                verified: true,
                message: 'verified'
            }
    } catch (error) {
        console.error('Verified Tokens Error: ' + error);
        throw {
            verified: false,
            message: 'invalid token'
        }
    }
    
}


export default generateToken;

Here's my verify.mjs code:

import buildResponse from '../utils/util.mjs';
import verifyTokens from '../utils/auth.mjs';


export async function verify(requestBody) {
    if(!requestBody.user || !requestBody.user.username || !requestBody.token) {
        return buildResponse(401, {
            verified: false,
            message: 'incorrect request body'
        })
    }
    
    const user = requestBody.user;
    const token = requestBody.token;
    try {
        console.error("Verifying this token=" + token);
        console.error("Verifying this user.username=" + user.username);
        const verification = await verifyTokens(user.username, token);
        console.error('Are we verified? verification.verified=', verification.verified);
        if(!verification.verified) {
            console.error("We are NOT verified! verification.verified=", verification.verified)
            return await buildResponse(401, verification);
        }
    }
    catch (error) {
        console.error("Error: ", error);
    }
   
    return buildResponse(200, {
        verified: true,
        message: 'success',
        user: user,
        token: token
    })
}

export default verify;

The log files show that I get to "Verifying this token" and "Verifying this user.username", but the log files never show the "Still inside verifyTokens" so I don't think it's calling this line.

const verification = await verifyTokens(user.username, token);

enter image description here


Solution

  • Explanation:

    As per MSN docs:

    Every module can have two different types of export, named export and default export. You can have multiple named exports per module but only one default export.

    You are already exporting multiple named exports such as generateToken and verifyTokens within your auth.mjs using Export Declarations when you used this syntax:

    export function generateToken(userInfo){
       //...
    }
    
    export async function verifyTokens(username, token) {
       //...
    }
    

    This means it can be confusing to also use export defualt syntax like you have done here in the same file:

    export default generateToken;
    

    Typically, using export defualt is for when you want to export a single variable, function or class. The knock-on effect in your code means that when you do this:

    import verifyTokens from '../utils/auth.mjs';
    

    The verifyTokens variable you just created now actually points to the generateToken function because you're now importing the default (which was generateToken). This is import to understand because when you try to execute verifyTokens() here:

    const verification = await verifyTokens(user.username, token);
    console.error('Are we verified? verification.verified=', verification.verified);
    

    What actually happened was this:

    const verification = await generateToken(user.username, token); //< token was ignored becuase generateToken only takes one parameter
    console.error('Are we verified? verification.verified=', verification.verified); //< verification.verified is undefined
    

    Solution:

    Simply import verifyTokens as one of the named exports using curly braces like so:

    import { verifyTokens } from '../utils/auth.mjs';