Привет, ребята, я сейчас пытаюсь сделать что-то похожее на то, что размещено здесь: Как для аутентификации запросов супертеста с помощью паспорта?
поскольку я хотел бы протестировать другие конечные точки, для которых требуется аутентификация, но, кроме того, необходимо передать файл jwt. Прямо сейчас я протестировал его в POSTMAN и в браузере, и кажется, что он работает нормально, но мои тестовые примеры продолжают ломаться. У меня есть маршрут POST для входа в систему, который настроен так:
AccountService.js
// Login POST route
router.post('/account_service/login', (req, res, next) => {
passport.authenticate('local-login', (err, user, info) => {
try {
if (err) {
const error = new Error('An Error occurred: Cannot find user');
return next(error);
} else if (!user) {
return res.redirect('/account_service/login');
}
req.login(user, { session: false }, (error) => {
if (error) {
return next(error);
}
const email = req.body.email;
const role = req.user[0].role;
const id = req.user[0].id;
const user = {
email: email,
role: role,
id: id
};
const accessToken = jwt.sign(user, config.ACCESS_TOKEN_SECRET, {
expiresIn: 28800 // expires in 8 hours
});
const cookie = req.cookies.cookieName;
if (cookie === undefined) {
// set a new cookie
console.log('setting new cookie');
res.cookie('jwt', accessToken, { maxAge: 900000, httpOnly: true });
res.send({ token: accessToken });
} else {
// cookie was already present
console.log('cookie exists', cookie);
}
res.redirect('/account_service/profile');
});
} catch (error) {
return next(error);
}
})(req, res, next);
});
После аутентификации пользователя я назначаю ему веб-токен JSON и помещаю его в файл cookie, чтобы он сохранялся в заголовках для авторизованных запросов. Вот пример:
AccountService.js
// Get all users
router.get('/account_service/all_users', passport.authenticate('jwt', { session: false }), (req, res, next) => {
const sql = 'select * from user';
const params = [];
db.all(sql, params, (err, rows) => {
if (err) {
res.status(500).json({ error: err.message });
return;
}
res.json({
message: 'success',
data: rows
});
});
});
Я использую password.authenticate, чтобы убедиться, что jwt действителен. Этот запрос GET работает только после того, как я вхожу в систему с учетной записью администратора.
В моем файле паспорта я настроил его так:
Passport.js
const LocalStrategy = require('passport-local').Strategy;
const db = require('../database.js');
const bcrypt = require('bcrypt');
const config = require('../config/config.js');
const JwtStrategy = require('passport-jwt').Strategy;
const cookieExtractor = function (req) {
var token = null;
if (req && req.cookies) token = req.cookies.jwt;
return token;
};
module.exports = function (passport) {
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, (req, email, password, done) => {
try {
const sql = `select * from user WHERE email = "${email}"`;
const params = [];
db.all(sql, params, (err, row) => {
if (err) {
return done(err);
}
if (!row.length || !bcrypt.compareSync(password, row[0].password)) {
return done(null, false, req.flash('loginMessage', 'Inavalid username/password combination. Please try again.'));
}
return done(null, row);
});
} catch (error) {
return done(error);
}
}));
const opts = {};
opts.jwtFromRequest = cookieExtractor; // check token in cookie
opts.secretOrKey = config.ACCESS_TOKEN_SECRET;
// eslint-disable-next-line camelcase
passport.use(new JwtStrategy(opts, function (jwtPayload, done) {
try {
const sql = `select * from user WHERE email = "${jwtPayload.email}"`;
const params = [];
db.all(sql, params, (err, row) => {
if (err) {
return done(err);
}
if (!row.length || !bcrypt.compareSync('admin', jwtPayload.role)) {
return done(null, false, { message: '403 Forbidden' });
}
return done(null, row);
});
} catch (error) {
return done(error);
}
}));
};
Вот где я запутываюсь, когда мои тестовые примеры ломаются. Я пытаюсь войти в систему перед тестовыми примерами, чтобы разрешить выполнение других моих тестовых примеров, но в итоге получаю ошибку 401. Вот мои тестовые примеры:
accountservice.test.js
const app = require('../../app');
const supertest = require('supertest');
const http = require('http');
describe('Account Service', () => {
let server;
let request;
beforeAll((done) => {
server = http.createServer(app);
server.listen(done);
request = supertest.agent(server);
request.post('/account_service/login')
.send({ email: '[email protected]', password: 'admin' })
.end(function (err, res) {
if (err) {
return done(err);
}
console.log(res);
done();
});
});
afterAll((done) => {
server.close(done);
});
it('Test request all users endpoint | GET request', async done => {
const response = await request.get('/account_service/all_users');
expect(response.status).toBe(200);
expect(response.body.message).toBe('success');
expect(response.body.data.length).toBe(3);
done();
});
});
Но мои тестовые примеры терпят неудачу, поскольку я получаю ошибку 401, когда ожидается успешный код 200.
Я попытался придумать способ извлечь jwt из файла cookie после вызова входа в систему, чтобы я мог настроить заголовки для кода запроса GET / account_service / all_users, но не смог найти способ с помощью Supertest. Я видел это сообщение: Проверка аутентифицированных маршрутов с помощью JWT не выполняется с использованием Мокко + супертест + паспорт но увидел что токен достает с тела.