Безопасно ли это промежуточное ПО для аутентификации и реализации маршрутов (Node.js / Express)? - PullRequest
0 голосов
/ 13 февраля 2020

В настоящее время я работаю над своим первым проектом node.js / реагировать, и я sh хочу начать собственно использовать проект, но боюсь, что может быть какая-то критическая уязвимость, о которой я не знаю. Я получил сертификат SSL, поэтому мне не нужно об этом беспокоиться, я также запускаю HTTPS (когда могу) и использую библиотеку шлемов.

У меня есть два основных промежуточных ПО аутентификации, которые я создал, одно для большинства маршрутов, а второй - для маршрута загрузки файла. Мне понадобилось отдельное промежуточное программное обеспечение для этих двух типов маршрутов, потому что я хотел использовать встроенную загрузку файлов, которая поставляется с веб-браузерами (в основном он щелкает по невидимой ссылке, чтобы запустить GET-запрос на загрузку файла.), И нет хороший способ отправить токен авторизации с этим запросом (без использования куки, которых я бы хотел избежать). Из-за этого, как я заявляю в комментариях к кодам, я сделал так, чтобы клиенту сначала нужно было получить временный токен и отправить его, так как его безопаснее (надеюсь) использовать в URL, потому что я сразу отозвал этот токен после маршрута аутентифицируется через промежуточное программное обеспечение.

Я разместил код ниже (с комментариями), если бы мог получить некоторую информацию, которая будет принята с благодарностью:

// Default Auth middleware for routes

const jwt = require("jsonwebtoken");
const User = require("../models/user");
const env = require("../enviroment/env");

const auth = async(req, res, next) => {

try {

    const token = req.header("Authorization").replace("Bearer ", "");

    const decoded = await jwt.verify(token, env.password);

    const user = await User.findOne({_id: decoded._id, "tokens.token": token})

    if (!user) {

        throw new Error("User not found")
    }

    req.token = token;
    req.user = user;

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

    // Should I throw an error here? As i state below, I have custom error
    // Objects I could throw instead. Or perhaps not wrap
    // This in a try or catch at all, and throw the
    // Error above?
    res.status(401).send({error: "Error Authenticating"})
}

next();
}

module.exports = auth;


// Example of a controller

async getFileInfo(req, res) {

    if (!req.user) {
        return;
        // Is this an anti-pattern? I have custom error objects
        // Should I throw inside of auth instead of checking
        // For user here?
    }

    try {

        const fileID = req.params.id;
        const userID = req.user._id;

        const file = await fileService.getFileInfo(userID, fileID);
        // The service/db utility also makes sure the userID matches the
        // User._id of the currently authenticated user. So an authenticated
        // User cannot get another users data.

        res.send(file);

    } catch (e) {

        const code = e.code || 500;
        // The customer error object appends an error
        // Code to itself, if its not an error thrown
        // It will use 500 as a default instead.

        console.log(e);
        res.status(code).send()
    }
}




// Middleware auth for file downloading

const jwt = require("jsonwebtoken");
const User = require("../models/user");
const env = require("../enviroment/env");

const tempAuth = async(req, res, next) => {

try {

    const token = req.params.tempToken;
    // This middleware requires a tempToken to first be acquired,
    // This is because I wish to use the built in browser
    // Download for files, and I cannot send an auth
    // Token when doing so (Without cookies, which i want to avoid).

    const decoded = await jwt.verify(token, env.password);

    const user = await User.findOne({_id: decoded._id, "tempTokens.token": token})
    // The tempToken is appended through a separate request,
    // That sends the tempToken to the client.

    user.tempTokens = user.tempTokens.filter((filterToken) => {

        return filterToken.token !== token
        // I immediately remove this tempToken after the token is verified,
        // Before the download even begins.  
    })


    await user.save();

    req.user = user;

    req.auth = true;

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

next();
}

module.exports = tempAuth;


// Controller For File Downloading

async downloadFile(req, res) {

    if (!req.auth || !req.user) {
        return await res.status(401).send("Please authenticate")
    }

    try {

        console.log("download request")

        const userID = req.user._id;
        const fileID = req.params.id;

        await fileService.downloadFile(userID, fileID, res);

    } catch (e) {

        const code = e.code || 500;
        const message = e.message || e;

        console.log(message, e);
        res.status(code).send();
    }
}


// Db Utility
this.getFileInfo = async(fileID, userID) => {

    const file = await conn.db.collection("fs.files")
        .findOne({"metadata.owner": userID, "_id": ObjectID(fileID)});
    // I also make sure the owner matches up with the current userID
    return file;
}

Примечание: Хотя я действительно хочу сделайте это приложение опубликованным c и с открытым исходным кодом на github в конце концов, я хочу подключиться только к своему домашнему веб-серверу (я размещаю этот сервер у себя дома и не использую какой-либо облачный сервис, я хотел сохранить все большие файлы загружаются локально.). Из-за этого внутри файла env я сделал возможность отключить создание учетной записи, поэтому после того, как я создал свою учетную запись, я активировал ее, создание учетной записи также запрещено на стороне сервера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...