Csurf неверный токен csrf Express / nodejs

У меня такое странное поведение. Я получаю сообщение об ошибке только при первой загрузке страницы, в основном это 'EBADCSRFTOKEN'. Я пытался понять, почему это происходит только при первой загрузке страницы, если Я нажимаю «Обновить» и получаю новый токен, все работает нормально.

тот же сценарий происходит, когда я удаляю файл cookie csurf, нажимаю «Обновить» и получаю новый токен, но в первый раз всегда происходит сбой. Я не уверен, почему ожидаемая строка и токен не совпадают.

фрагмент кода (я использую стек MEANJS):

app.use(busboy());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json({limit: '50mb'}));
app.enable('jsonp callback');

var cp = cookieParser;
app.use(cp());

var mStore = new mongoStore({
    db: db.connection.db,
    collection: config.sessionCollection
});

app.use(session({
    secret: config.sessionSecret,
    store: mStore,
    cookie: {httpOnly: false},
    key:config.cookieKey,
}));

app.use(csrf());

//setting up a middleware
var middlewareFiles = [
    'csrf-rule.server.js', 
    'secure-routes.server.js'
];

middlewareFiles.forEach(function(routeSecure){
    require(path.resolve('./app/middleware/'+routeSecure))(app);
});

app.use(function(err, req, res, next) {
    if (!err) return next();
        if(err.code === 'EBADCSRFTOKEN'){
            res.json(484, {data: 'invalid csrf token.'});
        return;
    }
   // Error page
    res.status(500).render('500', {
        error: err.stack
    });
});

Промежуточное ПО:

module.exports = function(app) {
    app.use(function(req, res, next){
        res.cookie('x-xsrf-token', req.csrfToken());
        res.locals.csrftoken = req.csrfToken();
        next();
    });
};

Различные значения токена:

Файл cookie

fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA

req.csrfToken() (в запросе промежуточного ПО)

fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA

Ожидается (в библиотеке csurf)

fgeHcu6v-T9CuTWL8hVGHMtSskeh0yzqaP0k

Токен (в библиотеке csurf)

fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA

похоже, что ожидаемое похоже на токен, и они отличаются сразу после тире, есть идеи?

ОБНОВЛЕНИЕ:

По сути, я последовал рекомендации @shakiba, удалил свое промежуточное ПО и позволил библиотеке csurf справиться с этим.

Я изменил конфигурацию на:

app.use(csrf({ cookie: true }));

теперь я получаю файл cookie с именем _csrf, теперь проблема немного другая, значение токена совпадает с секретным токеном в библиотеке, поэтому, когда библиотека преобразует секретный токен должен быть ожидаемым токеном, которому они не соответствуют.

Вот некоторые примеры значений:

Файл cookie BDir8-6hkdy-_YsXNb305IIx

Секрет BDir8-6hkdy-_YsXNb305IIx

Токен BDir8-6hkdy-_YsXNb305IIx

Ожидается BDir8-zbwt4-K_Uv8t1TtmxxctkfcMN1M


person pedrommuller    schedule 09.06.2015    source источник


Ответы (1)


Я считаю, что вы неправильно используете csurf, csurf устанавливает cookie за вас, вы не должны устанавливать его самостоятельно, и его значение отличается от значения csrfToken(). Насколько я понимаю из документов и исходного кода, значение csrfToken() генерируется с использованием значения, которое csurf устанавливает для файла cookie, поскольку они состояние для смягчения атаки BREACH.

Я сделал более простую версию csurf, которая использует только файлы cookie и ничего не делает с атакой BREACH, потому что атака BREACH кажется мне независимой проблемой, которую следует решать в независимом модуле/библиотеке. Я выложу его на github, чтобы вы могли использовать его, если хотите.

person Ali Shakiba    schedule 09.06.2015
comment
Я удалил свое промежуточное программное обеспечение и изменил конфигурацию на csrf({cookie: true}), чтобы создать собственный файл cookie, однако проблема все еще возникает, спасибо за помощь! - person pedrommuller; 10.06.2015
comment
Поэтому, пожалуйста, обновите свой вопрос, указав новый код и новую информацию об отладке, в том числе, где вы используете req.csrfToken() или res.locals.csrftoken. - person Ali Shakiba; 10.06.2015
comment
Я обновил вопрос, теперь у меня немного другой сценарий - person pedrommuller; 10.06.2015
comment
Как вы устанавливаете токен в своих запросах? Вы должны использовать req.csrfToken(), назначив его для просмотра локальных переменных, либо res.locals, как вы сделали в промежуточном программном обеспечении, либо res.render(view, locals). В настоящее время вы используете значение cookie/secret для токена. - person Ali Shakiba; 10.06.2015
comment
Я исправил это, передав req.csrfToken() в представление - person pedrommuller; 12.06.2015