title: Node js authentication in cross domain
body: <p>I am working on a <strong>MEAN</strong> application, I am using Angular 4 for my project. For authentication, I have implemented the Passport js <a href="https://github.com/jaredhanson/passport-local" rel="nofollow noreferrer"><code>Local-strategy</code></a>. And I am maintaining persistent session using <a href="https://github.com/expressjs/session" rel="nofollow noreferrer"><code>Express-session</code></a>. Things are working fine till here.</p>
  
  <p><strong>The Problem</strong></p>
  
  <p>In the same domain <code>session</code> works fine and I am able to authenticate the user. But in cross-domain, I am not able to maintain the session. It generates a new session id for each new request in cross-domain.</p>
  
  <p>I then tried <a href="https://github.com/themikenicholson/passport-jwt" rel="nofollow noreferrer"><code>Passport-jwt</code></a> but the problem with it is I don't have the control over user session. I mean I can't logout the user from the server if he is inactive or even on server re-start also the <code>token</code> don't get invalid.</p>
  
  <p>So in simple words, I am looking for an authentication solution in Node js (Express js) in which I can manage authentication in cross-domain.</p>
  
  <p>I have already seen some blog post and SO questions like <a href="https://stackoverflow.com/questions/19043511/passport-js-fails-to-maintain-session-in-cross-domain">this</a>, but it doesn't help.</p>
  
  <p>Thank you.</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Should I write my own code to achieve this? If so I have a plan.</p>
  
  <p>My basic plan is: </p>
  
  <ol>
  <li>The user will send credentials with the login request.</li>
  <li>I will check for the credentials in the database. If credentials are valid, I will generate a random token and save it to the database, in the user table and the same token I will provide to the user with success response.</li>
  <li>Now, with each request user will send the token and I will check the token for each request in the database. If the token is valid then I will allow the user to access the API otherwise I will generate an error with 401 status code.</li>
  <li>I am using Mongoose (MongoDB) so I will be ok to check the token in each request (performance point of view).</li>
  </ol>
  
  <p>I think this is also a good idea. I just want some suggestions, whether I am thinking in right direction or not.</p>
  
  <p>What I will get with this:</p>
  
  <ol>
  <li>The number of logged in user in the application (active sessions).</li>
  <li>I can logout a user if he is idle for a certain interval of time.</li>
  <li>I can manage multiple login session of the same user (by doing an entry in the database).</li>
  <li>I can allow the end user to clear all other login sessions (like Facebook and Gmail offers).</li>
  <li>Any customization related to authorization.</li>
  </ol>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>Here I am shareing my <code>app.js</code> code</p>
  
  <pre><code>var express = require('express');
  var helmet = require('helmet');
  var path = require('path');
  var favicon = require('serve-favicon');
  var logger = require('morgan');
  var cookieParser = require('cookie-parser');
  var bodyParser = require('body-parser');
  var dotenv = require('dotenv');
  var env = dotenv.load();
  var mongoose = require('mongoose');
  var passport = require('passport');
  var flash    = require('connect-flash');
  var session      = require('express-session');
  var cors = require('cors');
  
  var databaseUrl = require('./config/database.js')[process.env.NODE_ENV || 'development'];
  // configuration 
  mongoose.connect(databaseUrl); // connect to our database
  
  var app = express();
  
  // app.use(helmet());
  
  // required for passport
  
  
  app.use(function(req, res, next) {
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Origin', req.headers.origin);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
    if ('OPTIONS' == req.method) {
         res.send(200);
     } else {
         next();
     }
  });
  
  
  app.use(cookieParser());
  
  app.use(session({
      secret: 'ilovescotchscotchyscotchscotch', // session secret
      resave: true,
      saveUninitialized: true,
      name: 'Session-Id',
      cookie: {
        secure: false,
        httpOnly: false
      }
  }));
  
  
  require('./config/passport')(passport); // pass passport for configuration
  
  var index = require('./routes/index');
  var users = require('./routes/user.route');
  var seeders = require('./routes/seeder.route');
  var branches = require('./routes/branch.route');
  var companies = require('./routes/company.route');
  var dashboard = require('./routes/dashboard.route');
  var navigation = require('./routes/navigation.route');
  var roles = require('./routes/role.route');
  var services = require('./routes/services.route');
  
  // view engine setup
  app.set('views', path.join(__dirname, 'views'));
  app.set('view engine', 'jade');
  
  // uncomment after placing your favicon in /public
  //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
  app.use(logger('dev'));
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({ extended: true }));
  // app.use(cookieParser());
  app.use(express.static(path.join(__dirname, 'public')));
  
  app.use(passport.initialize());
  app.use(passport.session()); // persistent login sessions
  app.use(flash()); // use connect-flash for flash messages stored in session
  
  require('./routes/auth.route')(app, passport);
  app.use('/', index);
  app.use('/users', users);
  app.use('/seed', seeders);
  app.use('/branches', branches);
  app.use('/companies', companies);
  app.use('/dashboard', dashboard);
  app.use('/navigation', navigation);
  app.use('/roles', roles);
  app.use('/services', services);
  
  // catch 404 and forward to error handler
  app.use(function(req, res, next) {
    res.status(404).send({ status: 'NOT_FOUND', message: 'This resource is not available.'});
  });
  
  // error handler
  app.use(function(err, req, res, next) {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};
  
    // render the error page
    let errorObj = { 
      status: 'INTERNAL_SERVER_ERROR',
      message: 'Something went wrong.',
      error: err.message
    };
    res.status(err.status || 500).send(errorObj);
  });
  
  module.exports = app;
  </code></pre>
  
  <p><strong>EDIT 3</strong></p>
  
  <blockquote>
    <p>For those who don't understand my problem. Explaining the problem in
    simple words:</p>
  </blockquote>
  
  <ol>
  <li>My Express server is running on port 3000.</li>
  <li>In order to consume any API from the server, a user must be logged in.</li>
  <li>When a user gets logged in from <code>localhost:3000</code>, the server checks the credentials(using Passport-local) and returns a token in the response header.</li>
  <li>Now after login, when a user hits any API from <code>localhost:3000</code>, a predefined <code>Header</code> comes with <code>passport-session</code> and then passport verifies the user session using <code>req.isAuthenticated()</code> and all the things works as expected.</li>
  <li>When a user gets logged in from <code>localhost:4000</code> and the server send a token in response header (same as <code>localhost:3000</code>).</li>
  <li>When after successful login, the user hits any API from <code>localhost:4000</code> the passport js function <code>req.isAuthenticated()</code> returns <code>false</code>.</li>
  <li>This was happening because in cross-domain the <code>cookie</code> doesn't go to the server we need to set <code>withCredentials</code> header to <code>true</code> at the client side.</li>
  <li>I have set <code>withCredentials</code> header to <code>true</code> but still at the server the <code>req.isAuthenticated()</code> is returning <code>false</code>.</li>
  </ol>