Csurf невалиден csrf токен Express / nodejs

Имам това странно поведение. Получавам грешка само при първото зареждане на страницата ми, основно е 'EBADCSRFTOKEN' Опитвам се да разбера защо това се случва само при първото зареждане на страницата, ако Натискам опресняване и получавам нов токен, всичко работи добре.

същият сценарий се случва, когато изтрия бисквитката 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();
    });
};

Различни стойности за токена:

Бисквитка

fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA

req.csrfToken() (в заявка за междинен софтуер)

fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA

Очаква се (в csurf библиотека)

fgeHcu6v-T9CuTWL8hVGHMtSskeh0yzqaP0k

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

fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA

изглежда, че очакваното е подобно на токена и се различават точно след тирето, някакви идеи?

АКТУАЛИЗАЦИЯ:

По принцип последвах препоръката на @shakiba, премахнах персонализирания мидълуер и оставих csurf библиотеката да се справи с него.

Промених конфигурацията на:

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

сега получавам бисквитка с име _csrf, сега проблемът е малко по-различен, стойността на токена е същата като на тайния токен в библиотеката, така че когато библиотеката преобразува тайният токен да бъде очакваният токен, който не съвпада.

Това са някои примерни стойности:

Бисквитка BDir8-6hkdy-_YsXNb305IIx

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

Токен BDir8-6hkdy-_YsXNb305IIx

Очаква се BDir8-zbwt4-K_Uv8t1TtmxxctkfcMN1M


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


Отговори (1)


Вярвам, че не използвате правилно csurf, csurf задава бисквитката вместо вас, не трябва да я задавате сами и нейната стойност е различна от стойността на csrfToken(). Доколкото разбирам от документите и изходния код, стойността на csrfToken() се генерира с помощта на стойността, която csurf задава за бисквитката, тъй като те състояние за смекчаване на BREACH атака.

Направих по-опростена версия на csurf, която използва само бисквитки и не прави нищо срещу атаката BREACH, тъй като атаката BREACH ми изглежда като независим проблем, който трябва да бъде разгледан в независим модул/библиотека. Ще го споделя в github, за да можете да го използвате, ако желаете.

person Ali Shakiba    schedule 09.06.2015
comment
Премахнах мидълуера си, промених конфигурацията на csrf({cookie: true}), за да създам собствена бисквитка, но все още получавам проблема, благодаря за помощта! - 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). В момента използвате бисквитка/тайна стойност за токен. - person Ali Shakiba; 10.06.2015
comment
Поправих го, като предадох req.csrfToken() на изгледа - person pedrommuller; 12.06.2015