oauth-io / oauth-phonegap

OAuth.io plugin for Apache Cordova/PhoneGap
195 stars 69 forks source link

How to send CSRF information to the server? #51

Open mzarella opened 9 years ago

mzarella commented 9 years ago

How do I ensure that the proper csrf information is sent to the server? Currently my login handler looks like this:

  var app = angular.module('app');

  app.controller('LoginCtrl', function($scope, $state, UserService, $http, $cookies) {
    OAuth.initialize('LONG_STRING');
    var token = null;
    $http.get('http://api.example.com/oauth/token')
    .success(function(generatedToken, status) {
      return token = generatedToken;
    }).error(function(errorMessage, status) {
      return console.log("l8 LoginCtrl\n " + status + ": " + errorMessage);
    });

    // fired when touches the Google login button
    $scope.googleLogin = function() {
      return OAuth.popup('google', {
        cache: false,
        state: token
      }).done(function(result) {
        // so far so good, but this is where the request is invalid
        $http.post("http://api.example.com/oauth/signin")
        .success(function(data, status) {
          debugger;
        }).error(function(data, status) {
          debugger;
        });
      }).fail(function(error) {
        return console.log('error: ', error);
      });
    };

It's when I send a POST request to /oauth/signin that my server is unhappy: ForbiddenError: invalid csrf token

My express server code looks like this:

  var MongoStore, app, bodyParser, compress, connectAssets, contactController, cookieParser, csrf, csrfProtection, errorHandler, express, expressValidator, flash, homeController, logger, methodOverride, mongoose, multer, oauth, parseForm, passport, passportConf, path, secrets, session, userController;

  express = require('express');

  cookieParser = require('cookie-parser');

  csrf = require('csurf');

  compress = require('compression');

  session = require('express-session');

  bodyParser = require('body-parser');

  logger = require('morgan');

  errorHandler = require('errorhandler');

  methodOverride = require('method-override');

  multer = require('multer');

  MongoStore = require('connect-mongo')(session);

  flash = require('express-flash');

  path = require('path');

  mongoose = require('mongoose');

  passport = require('passport');

  expressValidator = require('express-validator');

  connectAssets = require('connect-assets');

  oauth = require('oauthio');

  csrfProtection = csrf({
    cookie: true
  });

  parseForm = bodyParser.urlencoded({
    extended: false
  });

  homeController = require('./controllers/home');

  userController = require('./controllers/user');

  contactController = require('./controllers/contact');

  secrets = require('./config/secrets');

  passportConf = require('./config/passport');

  app = express();

  mongoose.connect(secrets.db);

  mongoose.connection.on('error', function() {
    console.error('MongoDB Connection Error. Please make sure that MongoDB is running.');
  });

  app.set('port', process.env.PORT || 3000);

  app.set('views', path.join(__dirname, 'views'));

  app.set('view engine', 'jade');

  app.use(compress());

  app.use(connectAssets({
    paths: [path.join(__dirname, 'public/css'), path.join(__dirname, 'public/js')]
  }));

  app.use(logger('dev'));

  app.use(bodyParser.json());

  app.use(multer({
    dest: path.join(__dirname, 'uploads')
  }));

  app.use(expressValidator());

  app.use(methodOverride());

  app.use(cookieParser('secret'));

  app.use(session({
    resave: true,
    saveUninitialized: true,
    secret: secrets.sessionSecret,
    store: new MongoStore({
      url: secrets.db,
      autoReconnect: true
    })
  }));

  app.use(passport.initialize());

  app.use(passport.session());

  app.use(flash());

  app.use(csrf(), function(req, res, next) {
    res.cookie('XSRF-TOKEN', req.csrfToken());
    return next();
  });

  app.use(function(req, res, next) {
    res.locals.user = req.user;
    return next();
  });

  app.use(express["static"](path.join(__dirname, 'public'), {
    maxAge: 31557600000
  }));

/* I'm not using any of this right now
  app.get('/', homeController.index);

  app.get('/login', userController.getLogin);

  app.post('/login', userController.postLogin);

  app.get('/logout', userController.logout);

  app.get('/forgot', userController.getForgot);

  app.post('/forgot', userController.postForgot);

  app.get('/reset/:token', userController.getReset);

  app.post('/reset/:token', userController.postReset);

  app.get('/signup', userController.getSignup);

  app.post('/signup', userController.postSignup);

  app.get('/contact', contactController.getContact);

  app.post('/contact', contactController.postContact);

  app.get('/account', passportConf.isAuthenticated, userController.getAccount);

  app.post('/account/profile', passportConf.isAuthenticated, userController.postUpdateProfile);

  app.post('/account/password', passportConf.isAuthenticated, userController.postUpdatePassword);

  app.post('/account/delete', passportConf.isAuthenticated, userController.postDeleteAccount);

  app.get('/account/unlink/:provider', passportConf.isAuthenticated, userController.getOauthUnlink);
*/

  app.get('/oauth/token', csrfProtection, function(req, res) {
    var token = oauth.generateStateToken(req.session);
    return res.send(token);
  });

  app.post("/oauth/signin", parseForm, csrfProtection, function(req, res) {
    var code = req.body.code;
    return oauth.auth("google", req.session, {
      code: code
    }).then(function(request_object) {
      res.send(200, "The user is authenticated");
    }).fail(function(e) {
      console.log(e);
      return res.send(400, "Code is incorrect");
    });
  });

  app.use(errorHandler());

  app.listen(app.get("port"), function() {
    console.log("Express server listening on port %d in %s mode", app.get("port"), app.get("env"));
  });

  module.exports = app;

Here's the error code:

root@example:~/example-api# node index
Express server listening on port 3000 in development mode
GET /oauth/token 200 24.690 ms - 24
ForbiddenError: invalid csrf token
  at verifytoken (/root/example-api/node_modules/csurf/index.js:263:11)
  at csrf (/root/example-api/node_modules/csurf/index.js:93:7)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at /root/example-api/node_modules/express-flash/lib/express-flash.js:31:7
  at /root/example-api/node_modules/express-flash/node_modules/connect-flash/lib/flash.js:21:5
  at /root/example-api/node_modules/express-flash/lib/express-flash.js:22:5
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at SessionStrategy.strategy.pass (/root/example-api/node_modules/passport/lib/middleware/authenticate.js:318:9)
  at SessionStrategy.authenticate (/root/example-api/node_modules/passport/lib/strategies/session.js:67:10)
  at attempt (/root/example-api/node_modules/passport/lib/middleware/authenticate.js:341:16)
  at authenticate (/root/example-api/node_modules/passport/lib/middleware/authenticate.js:342:7)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at initialize (/root/example-api/node_modules/passport/lib/middleware/initialize.js:62:5)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at session (/root/example-api/node_modules/express-session/index.js:386:7)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at cookieParser (/root/example-api/node_modules/cookie-parser/index.js:34:14)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at methodOverride (/root/example-api/node_modules/method-override/index.js:77:5)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at /root/example-api/node_modules/express-validator/lib/express_validator.js:233:12
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at /root/example-api/node_modules/multer/index.js:218:19
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at jsonParser (/root/example-api/node_modules/body-parser/lib/types/json.js:103:37)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at logger (/root/example-api/node_modules/morgan/index.js:136:5)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at middleware (/root/example-api/node_modules/connect-assets/index.js:43:7)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at compression (/root/example-api/node_modules/compression/index.js:212:5)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at expressInit (/root/example-api/node_modules/express/lib/middleware/init.js:23:5)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at query (/root/example-api/node_modules/express/lib/middleware/query.js:28:5)
  at Layer.handle [as handle_request] (/root/example-api/node_modules/express/lib/router/layer.js:82:5)
  at trim_prefix (/root/example-api/node_modules/express/lib/router/index.js:302:13)
  at /root/example-api/node_modules/express/lib/router/index.js:270:7
  at Function.proto.process_params (/root/example-api/node_modules/express/lib/router/index.js:321:12)
  at next (/root/example-api/node_modules/express/lib/router/index.js:261:10)
  at Function.proto.handle (/root/example-api/node_modules/express/lib/router/index.js:166:3)
  at EventEmitter.app.handle (/root/example-api/node_modules/express/lib/application.js:170:10)
  at Server.app (/root/example-api/node_modules/express/lib/express.js:28:9)
  at Server.EventEmitter.emit (events.js:98:17)
  at HTTPParser.parser.onIncoming (http.js:2108:12)
  at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23)
  at Socket.socket.ondata (http.js:1966:22)
  at TCP.onread (net.js:525:27)

POST /oauth/signin 403 22.926 ms - -