2016-11-28 26 views
2

Я использую node 6.5.0 и npm 3.10.3.Ошибка токена CSRF (express.js)

Я получаю эту ошибку invalid csrf token, когда я пытаюсь войти на сайт.

{ ForbiddenError: invalid csrf token at csrf (/Users/Documents/web-new/node_modules/csurf/index.js:113:19)

Войти с хранением сессии в Redis работает без модуля csurf (https://github.com/expressjs/csurf). С модулем csurf идентификатор сеанса получает в redis, но я не могу вернуть правильный ответ клиенту для входа пользователя. Я использую Angular2 с node/express. Из того, что я понимаю, Angular2 по умолчанию поддерживает CSRF/XSRF с CookieXSRFStrategy при использовании HTTP-сервиса, поэтому все, что мне нужно сделать, это настроить что-то на стороне узла/экспресс. Приложение Angular2 с webpack-dev-сервером работает на localhost:3000, а узел/экспресс-сервер работает на localhost:3001. Я поддерживаю CORS.

Я могу видеть файл cookie с именем XSRF-TOKEN в devtools на localhost:3000.

Не могли бы вы порекомендовать, как я могу исправить эту ошибку?

//cors-middleware.js

var corsOptions = { 
    origin: 'http://localhost:3000', 
    credentials:true 
} 

app.use(cors(corsOptions)); 
app.use(function(req, res, next) { 
    res.setHeader('Content-Type','application/json'); 
     next(); 
    }) 
}; 

//index.js

import path from 'path'; 
import session from 'express-session'; 
import connectRedis from 'connect-redis'; 
import rp from 'request-promise'; 
import * as _ from 'lodash'; 
import cors from 'cors'; 
import csurf from 'csurf'; 

const redisStore = connectRedis(session); 
const dbStore = new redisStore(db); 

let baseUrl = app.getValue('baseUrl'); 

/* ~~ api authentication ~~ */ 

let options = { 
    method: 'POST', 
    url: `${baseUrl}/authenticate`, 
    rejectUnauthorized: false, 
    qs: { 
    username: 'someUsername', key: 'someKey' 
    }, 
    json: true 
}; 
rp(options) 
    .then(response => { 
     let apiToken = response.response; 
     app.setValue("token", apiToken); 
    }) 
    .catch(err => { 
     console.error(err); 
    }); 

/* ~~ configure session ~~ */ 

app.use(session({ 
    secret: app.getValue('env').SESSION_SECRET, 
    store: dbStore, 
    saveUninitialized: false, 
    resave: false, 
    rolling: true, 
    cookie: { 
     maxAge: 1000 * 60 * 30 // in milliseconds; 30 min 
    } 
})); 

/* ~~ login user ~~ */ 

let csrf = csurf(); 

app.post('/loginUser', csrf, (req, res, next) => { 
    let user = {}; 
    let loginOptions = { 
     method: 'POST', 
     url: `${baseUrl}/client/login`, 
     rejectUnauthorized: false, 
     qs: { 
      token: app.getValue('token'), 
      email: req.body.email, 
      password: req.body.password 
     }, 
     headers: { 
      'Content-Type': 'application/json' 
     }, 
     json: true 
    }; 

    rp(loginOptions) 
     .then(response => { 
      let userToken = response.response.token; 
      let clientId = response.response.clientId; 

      req.session.key = req.session.id; 

      user.userToken = userToken; 
      user.clientId = clientId; 


      let clientAttributeOptions = { 
       url: `${baseUrl}/client/${clientId}/namevalue`, 
       rejectUnauthorized: false, 
       qs: { 
        token: app.getValue('token'), 
        usertoken: userToken 
       }, 
       json: true 
      }; 

      return rp(clientAttributeOptions); 
     }) 
     .then(response => { 
      req.session.user = user; 
       res.send({user:user}) 
     }) 
     .catch(err => { 
      next(err); 
     }) 

}); 

ответ

0

Мой вопрос заключается в том, что я в том числе функцию CSRF в качестве промежуточного слоя только в app.post('/loginUser) маршруте.

Когда я включил его для всех маршрутов, модуль работал нормально.
let csrf = csurf(); app.get('/*', csrf, (req, res) => { res.sendFile(app.get('indexHTMLPath')); });