У меня есть простая программа с Auth и Todo-App, например, «Микросервис».
Я реализовал базовый c поток аутентификации:
- Пользователь входит в систему с учетными данными
- Возвращает токен, срок действия которого истекает через 15 минут
- A
httpOnly
cook ie устанавливается с помощью refre sh token - Теперь пользователь может вызывать
/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'
});
}
};