Как использовать требование jti в JWT
В спецификации JWT упоминается требование jti, которое предположительно может использоваться как nonce для предотвращения повторных атак:
Заявка jti (JWT ID) предоставляет уникальный идентификатор для JWT. Значение идентификатора ДОЛЖНО назначаться таким образом, чтобы гарантировать, что существует незначительная вероятность того, что одно и то же значение будет случайно присвоено другому объекту данных; если приложение использует несколько эмитентов, коллизии ДОЛЖНЫ быть предотвращены среди значений, произведенных разными эмитентами. Требование jti может использоваться для предотвращения повторного воспроизведения JWT. Значение jti является строкой, чувствительной к регистру. Использование этого требования ДОПОЛНИТЕЛЬНО.
Мой вопрос в том, как я могу это реализовать? Нужно ли мне хранить ранее использованные jtis и выдавать новый JWT с каждым запросом? Если это так, разве это не побеждает цель JWT? Зачем использовать JWT вместо того, чтобы просто хранить случайно сгенерированный идентификатор сеанса в базе данных?
В моем REST API есть база данных mongo, и я не возражаю против добавления экземпляра redis. Есть ли лучший вариант проверки подлинности, чем JWT? В основном я просто не хочу хранить пароли на клиенте, что исключает HTTP-аутентификацию в качестве опции, однако, поскольку я все глубже проникаю в этот материал JWT, я начинаю чувствовать, что может быть реализована обычная реализация токена или другой стандарт удовлетворить мои потребности. Существуют ли node/express пакеты для проверки подлинности на токенах, которые поддерживают маркерные аннулирования и поворота маркеров?
Поблагодарили бы за любой совет.
Ответы
Ответ 1
Действительно, хранение всех выданных JWT-идентификаторов подрывает апатридный характер использования JWT. Однако цель JWT ID - отменить ранее выпущенные JWT. Этого легче всего добиться путем "черного списка" вместо "белого списка". Если вы включили требование "exp" (вы должны), вы можете в конечном итоге очистить черные списки JWT, поскольку они истекают естественным путем. Конечно, вы можете реализовать другие варианты отзыва рядом (например, аннулировать все токены одного клиента на основе комбинации "iat" и "aud" ).
Ответ 2
Вы можете использовать пакет express-jwt
См. express-jwt на GitHub или на NPM.
Express-jwt обрабатывает отозванные маркеры, как описано здесь: https://github.com/auth0/express-jwt#revoked-tokens
var jwt = require('express-jwt');
var data = require('./data');
var utilities = require('./utilities');
var isRevokedCallback = function(req, payload, done){
var issuer = payload.iss;
var tokenId = payload.jti;
data.getRevokedToken(issuer, tokenId, function(err, token){
if (err) { return done(err); }
return done(null, !!token);
});
};
app.get('/protected',
jwt({secret: shhhhhhared-secret,
isRevoked: isRevokedCallback}),
function(req, res) {
if (!req.user.admin) return res.send(401);
res.send(200);
});
Вы также можете прочитать часть 4. Как избежать дополнительных накладных расходов? от это сообщение в oauth0.