Chaining 2 auth tokens in one endpoint

Viewed 38

I'm trying to chain 2 auth tokens in one endpoint, the user and the admin, to get all merchants.

I have tried several solutions posted by several people here on stackoverflow, with no luck. I'll post my code along with the solutions I tried below.

How can I make express to continue the process if the request has ONE of the 2 tokens, admin OR user?

Thanks in advance...

Admin auth:

const adminAuth = async (req, res, next) => {
    try {
        const token = req.header('Authorization');
        if(!token) {
            return res.status(401).json({ message: 'Unauthorized', success: false });
        }

        const newToken = req.header('Authorization').split(' ')[1];

        const decoded = JWT.verify(newToken, key);

        if(decoded.role != 'admin') {
            return res.status(401).json(
                { message: 'Unauthorized, only an admin is authorized!', success: false }
            );
        }

        const findAdmin = await Admin.findOne({ username: decoded.username });
        if(!findAdmin){
            return res.status(409).send({ message: `Admin doesn't exist!`, success: false });
        }

    } catch (err) {
        console.log(err);
    }

    next();
}

User auth:

const userAuth = async (req, res, next) => {
    try {
        const token = req.header('Authorization');
        if(!token) {
            return res.status(401).json({ message: 'Unauthorized', success: false });
        }

        const newToken = req.header('Authorization').split(' ')[1];

        const decoded = JWT.verify(newToken, key);

        if(decoded.role != 'user') {
            return res.status(401).json({ message: 'Unauthorized, only a user is authorized!', success: false });
        }

        const findUser = await User.findOne({ email: decoded.email });
        if(!findUser){
            return res.status(409).send({ message: `User doesn't exist!`, success: false });
        }

    } catch (err) {
        console.log(err);
    }

    next();
}

The endpoint in question:

router.get('/getall', adminAuth, usertAuth, upload.none(), async (req, res) => {
    const merchantsList = await Merchant.find();

    if(!merchantsList) {
        return res.status(500).send({ success: false });
    }
    return res.status(200).send({ merchants: merchantsList, success: true });
});

I tried the below solutions:

router.get('/getall', [adminAuth, usertAuth], upload.none(), async (req, res) => {
    const merchantsList = await Merchant.find();

    if(!merchantsList) {
        return res.status(500).send({ success: false });
    }
    return res.status(200).send({ merchants: merchantsList, success: true });
});

router.get('/getall', [adminAuth || usertAuth], upload.none(), async (req, res) => {
    const merchantsList = await Merchant.find();

    if(!merchantsList) {
        return res.status(500).send({ success: false });
    }
    return res.status(200).send({ merchants: merchantsList, success: true });
});

router.get('/getall', [adminAuth, usertAuth, upload.none(), async (req, res) => {
    const merchantsList = await Merchant.find();

    if(!merchantsList) {
        return res.status(500).send({ success: false });
    }
    return res.status(200).send({ merchants: merchantsList, success: true });
}]);

router.get('/getall', [adminAuth, usertAuth, upload.none()], async (req, res) => {
    const merchantsList = await Merchant.find();

    if(!merchantsList) {
        return res.status(500).send({ success: false });
    }
    return res.status(200).send({ merchants: merchantsList, success: true });
});
1 Answers

That's not how middlewares work in express for example let's look at getAll route

router.get('/getall', [adminAuth, usertAuth], upload.none(), async (req, res) => {
   try{
     //some code
   }catch(e){ 
    //handle error 
   } 
}); 

if the user is not admin it will fail at adminAuth and end the request, so you have to think of middlewares as a chain or a pipleline they pass (req,res,next) to each other

so what you need here is not make a third middleware which is the combination of adminAuth and userAuth

async function adminAndUserAuth (req, res, next){
    try {
        const token = req.header('Authorization');
        if(!token) {
            return res.status(401).json({ message: 'Unauthorized', success: false });
        }

        const newToken = req.header('Authorization').split(' ')[1];

        const decoded = JWT.verify(newToken, key);

        if(decoded.role != 'admin' && decoded.role  != 'user' ) {
            return res.status(401).json(
                { message: 'Unauthorized, only an admin or user are authorized!', success: false }
            );
        }
        const found = await Admin.findOne({ username: decoded.username }) ?? await   User.findOne({ email: decoded.email });
        
        if(!found){
            return res.status(409).send({ message: `Admin doesn't exist!`, success: false });
        }

    } catch (err) {
        console.log(err);
    }

    next();
}

and the new route will be

router.get('/getall' , adminAndUserAuth , async (req,res) => {});
Related