Микросервисы и рефр sh токены NodeJS - PullRequest
0 голосов
/ 30 марта 2020

У меня есть простая программа с Auth и Todo-App, например, «Микросервис».

Я реализовал базовый c поток аутентификации:

  1. Пользователь входит в систему с учетными данными
  2. Возвращает токен, срок действия которого истекает через 15 минут
  3. A httpOnly cook ie устанавливается с помощью refre sh token
  4. Теперь пользователь может вызывать /todos маршрут, передавая токен в виде тела запроса

Клиентское приложение (WebBrowser) автоматически вызывает /refresh_token, чтобы обновить токен и refresh_token

Нужно ли также сохранять маркеры refre sh в базе данных пользователей и проверять их при каждом запросе /refresh_token? Будут ли еще какие-нибудь хорошие методы обеспечения безопасности или улучшения в том, как я реализовал поток аутентификации?

AuthService

const express = require('express');
const jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');

const PORT = 3001;
const app = express();
app.use(cookieParser('secret3'));

const user = {
    id: 1,
    username: 'sam',
    password: '123',
    ref_token: '' //
};

//Generate token and refresh token
app.post('/login', (req, res) => {
    const payload = {
        id: user.id
    };

    const token = jwt.sign(payload, 'secret', { expiresIn: '15m' });
    const refreshToken = jwt.sign(payload, 'secret2', { expiresIn: '60d' });

    //Save refresh token to users db row

    //Set refresh token in httpOnly cookie
    let options = {
        maxAge: 1000 * 60 * 60 * 24 * 30, // would expire after 1month
        httpOnly: true,
        signed: true
    };
    res.cookie('rt', refreshToken, options);

    res.json({
        token: token,
        message: 'Login successful'
    });

});

//Generates a new jwt and a refresh token from prev refresh token
app.get('/refresh_token', (req, res) => {
    //Get the refresh token from cookie
    const { rt } = req.signedCookies;
    if (rt == null) {
        return res.json({
            message: 'Missing rt cookie'
        });
    }

    //Verify refresh token against users db here...

    //New authtoken and refreshtoken
    const payload = {
        id: user.id
    };

    const token = jwt.sign(payload, 'secret', { expiresIn: '15m' });
    const refreshToken = jwt.sign(payload, 'secret2', { expiresIn: '60d' });

    //Update new refreshToken in DB

    //Set refresh token in httpOnly cookie
    let options = {
        maxAge: 1000 * 60 * 60 * 24 * 30, // would expire after 1month
        httpOnly: true,
        signed: true
    };
    res.cookie('rt', refreshToken, options);

    res.json({
        token: token,
        message: 'New tokens generated'
    });

});

app.listen(PORT, () => {
    console.log(`Auth microservice running on ${PORT}`)
});

TodoService

const express = require('express');
const verifyToken = require('./verifyjwt.js');
const bodyParser = require('body-parser');

const PORT = 3002;
const app = express();
app.use(bodyParser());

const todos = [
    {
       id: 1,
       belongsTo: 1,
       content: 'Buy milk',
       isDone: true
    },
    {
        id: 346457,
        belongsTo: 5436,
        content: 'Clean your desktop',
        isDone: false
    }
];

//Return user todos (protected route)
app.get('/todos', verifyToken,(req, res) => {
    //Find where req.decoded.id matches todos.belongsTo...
    res.send(todos[0]);
});

app.listen(PORT, () => {
    console.log(`Todo microservice running on port ${PORT}`);
});

verifyjwt.js

const jwt = require('jsonwebtoken');

module.exports = (req,res,next) => {
    const token = req.body.token;
    //Decode token
    if (token) {
        //Verify secret and exp
        jwt.verify(token, 'secret', function(err, decoded) {
            if (err) {
                return res.status(401).json({"message": 'Unauthorized access'});
            }
            req.decoded = decoded;
            next();
        });
    } else {
        return res.status(403).send({
            "message": 'No token provided'
        });
    }
};

1 Ответ

0 голосов
/ 31 марта 2020

То, что вы сделали, в основном выглядит хорошо. Поскольку вы используете JWT, вам не нужно искать пользователя в базе данных, поскольку только вы знаете секрет JWT, поэтому, проверив JWT, вы сможете использовать декодированный идентификатор пользователя и узнать, что он является правильным пользователем.

Единственное, для чего вы можете рассмотреть возможность использования базы данных, - сделать недействительными токены, которые недействительны, например, если пользователь выходит из системы, что вы, вероятно, можете сделать, просто сохранив время последнего выхода из системы в базе данных, а затем перед введением нового refre sh token, проверьте время последнего выхода из системы и время выпуска предыдущего токена.

Единственное, что вам нужно изменить, что, я уверен, является преднамеренным для отладки, это использовать значение req.decoded.id для ИД пользователя, а не его жестко закодированный.

Еще одна вещь, которую я заметил в вашем коде, в вашей функции jwt.verify, вы возвращаете свое несанкционированное сообщение в обратном вызове, который, я думаю, просто проглотит, вызывая запрос зависание, если токен недействителен.

...