Elijah Arhinful
Elijah Arhinful

Reputation: 21

Web session is not created when I open my website on a mobile device

I have this e-commerce site created with node, mongodb and express. It is hosted on heroku and this is the url: https://elisales.herokuapp.com/. The login is working perfectly on desktop but when I open the website on any mobile phone, the login does not work. You can use username : dee & password: dee to login.

I tailed the logs on heroku and there is no error message. I logged the session to the console and found out that the result is null when I open it on the mobile phone but the session is created when the site is opened on desktop. I can't seem to find the problem. Any help? This is the first project I have ever completed.

This is a link to the GitHub repo: https://github.com/elijaharhinful/e-commerce

This is a copy of my index.js

require('dotenv').config();
const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const config = require('./config/database')
const session = require('express-session')
const expressValidator = require('express-validator');
const fileUpload = require('express-fileupload');
const passport = require('passport');
const MongoStore = require('connect-mongo');

//conect to database
main().catch(err => console.log(err));

async function main() {
  if (process.env.NODE_ENV === "development") {
    await mongoose.connect(config.database)
    console.log('Connected to MongoDB local')

  } else if (process.env.NODE_ENV === "production") {
    await mongoose.connect(process.env.MONGODB_URL)
    console.log('Connected to MongoDB atlas')
  }
}


//init app
let app = express();

//view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

//set public folder
//app.use(express.static('public'));
app.use(express.static(path.join(__dirname, 'public')));


//set global errors variable
app.locals.errors = null;

// Get Page Model
let Page = require('./models/page');

// Get all pages to pass to header.ejs
Page.find({}).sort({sorting: 1}).exec(function (err, pages) {
    if (err) {
        console.log(err);
    } else {
        app.locals.pages = pages;
    }
});

// Get Category Model
let Category = require('./models/category');

// Get all categories to pass to header.ejs
Category.find(function (err, categories) {
    if (err) {
        console.log(err);
    } else {
        app.locals.categories = categories;
    }
});

// Express fileUpload middleware
app.use(fileUpload());

//body parser middleware
app.use(express.urlencoded({ extended: false}))
app.use(express.json());

// Express Session middleware
if (process.env.NODE_ENV === "development"){
  app.use(session({
    secret: process.env.SESS_KEY,
    resave: true,
    saveUninitialized: true,
    store: MongoStore.create({
      mongoUrl: config.database,
      ttl: 5 * 24 * 60 * 60 // = 5 days.
    })
    //  cookie: { secure: true }
  }));
}else if (process.env.NODE_ENV === "production"){
  app.set('trust proxy', 1); // trust first proxy
  app.use(session({
    secret: process.env.SESS_KEY,
    resave: true,
    saveUninitialized: true,
    cookie: { secure: true },
    store: MongoStore.create({
      mongoUrl: process.env.MONGODB_URL,
      ttl: 1 * 24 * 60 * 60 // = 1 day.
    })
  }));
}


// Express Validator middleware
app.use(expressValidator({
  errorFormatter: function (param, msg, value) {
    let namespace = param.split('.'),
      root = namespace.shift(),
      formParam = root;

    while (namespace.length) {
      formParam += '[' + namespace.shift() + ']';
    }
    return {
      param: formParam,
      msg: msg,
      value: value
    };
  },
  customValidators: {
    isImage: function (value, filename) {
      let extension = (path.extname(filename)).toLowerCase();
      switch (extension) {
        case '.jpg':
          return '.jpg';
        case '.jpeg':
          return '.jpeg';
        case '.png':
          return '.png';
        case '':
          return '.jpg';
        default:
          return false;
      }
    }
  }
}));


//Express Messages middleware
app.use(require('connect-flash')());
app.use(function (req, res, next) {
    res.locals.messages = require('express-messages')(req, res);
    next();
});

// Passport Config
require('./config/passport')(passport);

// Passport Middleware
app.use(passport.initialize());
app.use(passport.session());

app.get('*', function(req,res,next) {
  res.locals.cart = req.session.cart;
  res.locals.user = req.user || null;
  next();
});

// Set routes 
const pages = require('./routes/pages.js');
const products = require('./routes/products.js');
const cart = require('./routes/cart.js');
const users = require('./routes/users.js');
const adminPages = require('./routes/admin_pages.js');
const adminCategories = require('./routes/admin_categories.js');
const adminProducts = require('./routes/admin_products.js');
const database = require('./config/database');

app.use('/admin/pages', adminPages);
app.use('/admin/categories', adminCategories);
app.use('/admin/products', adminProducts);
app.use('/products', products);
app.use('/cart', cart);
app.use('/users', users);
app.use('/', pages);

app.use(function (req, res) {
  res.status(404);
  res.render('404');
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500);
  res.render('500');
});

//start the server

let PORT = process.env.PORT || 3000;
app.listen(PORT, function () {
  console.log('App is running on http://localhost:' + PORT);
});

And this is my user.js

require('dotenv').config();
const express = require('express');
const router = express.Router();
const passport = require('passport');
const bcrypt = require('bcryptjs');
const async = require('async');
const crypto = require('crypto');
const nodemailer = require('nodemailer');
const { google } = require('googleapis');
const OAuth2 = google.auth.OAuth2

// Get Users model
let User = require('../models/user');

// Get Tokens model
let Token = require('../models/token');


const OAuth2_client = new OAuth2(process.env.CLIENT_ID, process.env.CLIENT_SECRET)
OAuth2_client.setCredentials( { refresh_token : process.env.REFRESH_TOKEN } )
const accessToken = OAuth2_client.getAccessToken()

/*
 * GET register
 */
router.get('/register', function (req, res) {

    res.render('register', {
        title: 'Register'
    });

});

/*
 * POST register
 */
router.post('/register', function (req, res) {

    let name = req.body.name;
    let email = req.body.email;
    let username = req.body.username;
    let password = req.body.password;
    let password2 = req.body.password2;

    req.checkBody('name', 'Name is required!').notEmpty();
    req.checkBody('email', 'Email is required!').isEmail();
    req.checkBody('username', 'Username is required!').notEmpty();
    req.checkBody('password', 'Password is required!').notEmpty();
    req.checkBody('password2', 'Passwords do not match!').equals(password);

    let errors = req.validationErrors();

    if (errors) {
        res.render('register', {
            errors: errors,
            user: null,
            title: 'Register'
        });
    } else {
        User.findOne({
            username: username
        }, function (err, user) {
            if (err)
                console.log(err);

            if (user) {
                req.flash('danger', 'Username exists, choose another!');
                res.redirect('/users/register');
            } else {
                let user = new User({
                    name: name,
                    email: email,
                    username: username,
                    password: password,
                    admin: 0
                });

                bcrypt.genSalt(10, function (err, salt) {
                    bcrypt.hash(user.password, salt, function (err, hash) {
                        if (err)
                            console.log(err);

                        user.password = hash;

                        user.save(function (err) {
                            if (err) {
                                console.log(err);
                            } else {
                                crypto.randomBytes(16, function (err, buf) {

                                    if (err) console.log(err);

                                    let token = new Token({
                                        _userId: user.id,
                                        token: buf.toString('hex')
                                    });

                                    token.save(function (err) {
                                        if (err) {
                                            console.log(err);
                                        } else {
                                            async function main() {
                                                //let testAccount = await nodemailer.createTestAccount();

                                                // create reusable transporter object using the default SMTP transport
                                                let transporter = nodemailer.createTransport({
                                                    service: 'gmail',
                                                    auth: {
                                                        type: 'OAuth2',
                                                        user: process.env.MAIL_USERNAME, // generated ethereal user
                                                        pass: process.env.MAIL_PASSWORD,
                                                        clientId: process.env.CLIENT_ID,
                                                        clientSecret: process.env.CLIENT_SECRET,
                                                        refreshToken: process.env.REFRESH_TOKEN,
                                                        accessToken: accessToken
                                                    },
                                                });

                                                // send mail with defined transport object
                                                await transporter.sendMail({
                                                    from: '"My Website 👻"[email protected]', // sender address
                                                    to: user.email, // list of receiver (s)
                                                    subject: "Verify your My Website email", // Subject line
                                                    text: 'Hello ' + user.username + ',\n\n' +

                                                        'Thanks for signing up with My Website! Before you get started, we need you to confirm your email address. Please click the link below to complete your signup.\n\n' +
                                                        'http://' + req.headers.host + '/users/confirm-email/' + token.token + '\n\n' +

                                                        'If you have any trouble clicking the link, please copy and paste the URL into your prefered web browser.\n\n' +

                                                        'If you did not request this, please ignore this email.\n' // html body
                                                });

                                                req.flash('info', 'A verification e-mail has been sent to ' + user.email + ' with further instructions.');
                                                res.redirect('/users/register-token')
                                            }
                                            main().catch(console.error);

                                        }
                                    });

                                });
                            }
                        });
                    });
                });
            }
        });
    }

});


 
/*
 * GET login
 */
router.get('/login', function (req, res) {

    if (res.locals.user) res.redirect('/');

    res.render('login', {
        title: 'Log in'
    });

});

/*
 * POST login
 */
router.post('/login', function (req, res, next) {

    passport.authenticate('local', {
        successRedirect: '/',
        failureRedirect: '/users/login',
        isVerified: '/users/login',
        failureFlash: true
    })(req, res, next);

});

/*
 * GET logout
 */
router.get('/logout', function (req, res) {

    req.logout();

    req.flash('success', 'You are logged out!');
    res.redirect('/users/login');

});

Upvotes: 1

Views: 206

Answers (1)

Elijah Arhinful
Elijah Arhinful

Reputation: 21

I have found a solution!!! The problem was I had set the "cookie secure" option to "true". On the desktop the website was opening with "https://" hence the cookie was working perfectly. On the mobile phone it opens with "http://" and that was a problem because secure cookies can't be sent over insecure urls.

The solution was to replace the "http://" with "https://" when entering the url on the mobile phone and that solved it.

Read more here: https://www.npmjs.com/package/express-session

Upvotes: 1

Related Questions