MERN stack error on production with mongodb - node.js

I try to deploy a MERN stack on ubuntu Nginx but i have the following error:
0|app | Assertion failed: You must provide either mongoUrl|clientPromise|client in options
0|app | Error: Cannot init client. Please provide correct options
0|app | at new MongoStore (/root/sites/vadasz-backend/node_modules/connect-mongo/build/main/lib/MongoStore.js:119:19)
I have checked the credentials for mango db
everything works on my local machine but as soon as i try to deploy on a VPS it suddenly stop working.
This is my mongo settings:
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const MongoStore = require("connect-mongo");
dotenv.config();
mongoose.set("strictQuery", true);
mongoose.connect(process.env.MONGO_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const connection = mongoose.connection;
try {
connection.once("open", () => {
console.log("database connected successfully...");
});
} catch (error) {
console.log("connection failed...");
}
let store = new MongoStore({
mongoUrl: process.env.MONGO_URL,
collection: "sessions",
});
app.use(
session({
secret: process.env.SESS_SECREET,
resave: false,
saveUninitialized: true,
store: store,
cookie: {
secure: "auto",
},
})
);
Is there any advise ?

Changing this line
dotenv.config();
to this line
dotenv.config({debug: true, path: __dirname + '/.env'});
solved the problem.

Related

UnhandledPromiseRejectionWarning: Error: The client is closed on NodeJS

I am trying to add Redis to my website for session management but I get the below error:
UnhandledPromiseRejectionWarning: Error: The client is closed
Below is my code:
I have kept only the relevant redis lines to avoid verbosity.
const express = require('express');
const app = express();
const session = require('express-session');
const redis = require('redis');
const connectRedis = require('connect-redis');
const RedisStore = connectRedis(session)
const redisClient = redis.createClient({
host: 'localhost',
port: 6379
})
redisClient.on('error', function (err) {
console.log('Could not establish a connection with redis. ' + err);
});
redisClient.on('connect', function (err) {
console.log('Connected to redis successfully');
});
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'secret$%^134',
resave: false,
saveUninitialized: false,
cookie: {
secure: false, // if true only transmit cookie over https
httpOnly: false, // if true prevent client side JS from reading the cookie
maxAge: 1000 * 60 * 10 // session max age in miliseconds
}
}))
app.use(
session({
name: 'AuthCookie',
secret: 'some secret string!',
resave: false,
saveUninitialized: true
})
);
app.listen(port, () => {
console.log("We've now got a server!");
console.log('Your routes will be running on http://localhost:3000');
});
I read that I should add await client.connect() but I am not sure

My cookie is not set in Browser of studio.apollographql explorer

i am trying to set cookie on apollo Studio explorer, my redis setup successfully store the cookie, but nothing is set on the browser.
Please What am i doing wrong ?
when make a monitoring of redis with redis-cli ,i can see that the token is receive.
i am using : apollo-server-express "^3.3.0", and express-session "^1.17.2"
async function startServer() {
const app = express();
const httpServer = http.createServer(app);
const RedisStore = connectRedis(session);
const redisClient = redis.createClient({
host: "127.0.0.1",
port: 6379,
});
app.use(
session({
name: "pid",
store: new RedisStore({
client: redisClient,
}),
cookie: {
maxAge: 1000 * 60 * 10,
httpOnly: false,
secure: true,
sameSite: "none",
},
saveUninitialized: false,
secret: "EOJ7OmvIAhb2yJpCI947juj6F8CppHCp",
resave: false,
})
);
const server = new ApolloServer({
schema,
context: createContext,
formatError: (error) => {
return {
message: error.message,
};
},
});
await server.start();
server.applyMiddleware({
app,
cors: { credentials: true, origin: "https://studio.apollographql.com" },
});
await new Promise((resolve: any) =>
httpServer.listen({ port: process.env.PORT }, resolve)
);
}
startServer().catch((err) => console.log(err));

Storing sessions with express-session, connect-mongo, and mongoose

I am looking for guidance on setting up session based authentication with with Express-Session, connect-mongo, and Mongoose. Currently it's just generating a new UUID with every request and not saving anything to the sessions collection. Am I missing something obvious?
index.js
const mongoose = require("./db/connection");
const express = require("express");
const cors = require('cors')
const session = require('express-session')
const MongoStore = require("connect-mongo");
const app = express();
const { v4: uuidv4 } = require('uuid');
//Register .env file
require('dotenv').config()
//Middleware
app.use(express.json());
app.use(session({
genid: (req) => {
return uuidv4()
},
secret: process.env.EXPRESS_SESSION_SECRET,
resave: true,
saveUninitialized: false,
cookie: { maxAge: 24 * 60 * 60 * 1000 },
store: MongoStore.create({
client: mongoose.connection.getClient(),
dbName: process.env.MONGO_DB_NAME,
collectionName: "sessions",
stringify: false,
autoRemove: "interval",
autoRemoveInterval: 1
})
})
);
connection.js
const mongoose = require("mongoose");
require('dotenv').config()
mongoose.connect(`mongodb://devroot:devroot#localhost:27017/${process.env.MONGO_DB_NAME}?authSource=admin`, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true
});
mongoose.connection
.on("open", () => console.log("The goose is open"))
.on("close", () => console.log("The goose is closed"))
.on("error", (error) => {
console.log(error);
process.exit();
})
module.exports = mongoose;
The setting saveUninitialized: false means that a session is established only if it contains some information, that is, if a statement like req.session.attribute = "value" is executed during request processing. If that does not happen, the session is not stored, and also no session cookie issued, so that the next request triggers a new session (with a new UUID), but which may again not be stored.
The author probably "solved" the issue by setting saveUninitialized: true, but this has the following consequences:
Every visitor to the website creates a new session entry (without any information in it) in the database even if they never interact with the site nor log on.
Every visitor gets a session cookie in their browser even before actually logging on.
I consider both these consequences undesirable and would therefore prefer saveUninitialized: false so that sessions without information are effectively not created.
Posting for visibility; this was related to:
saveUninitialized: false
Changing this to true forces save to the store.

Express-session not set cookies in the browser after deploying the server application on the Heroku platform

I faced the issue with express-session and I have tried to solve it.
Here is what I found some solutions.
https://github.com/expressjs/session/issues/633
But honestly to say it doesn't work for me.
When I run a server on my local machine everything works fine and the cookie set and contained in the browser.
But I have no idea why after deploying on the Heroku platform the cookie option not set and not contained in the browser.
Configuration
import {DB_HOST} from "./configs/database";
import {PORT} from "./configs";
import session from "express-session";
import mongoDBSession from 'connect-mongodb-session'
//Session db
const DBSessions = mongoDBSession(session)
//Create express app
const app = express();
app.use('/public', express.static('public'))
//Config Object to Avoid Deprecation Warnings
const dbOptions = {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
};
//MongoDB
//Connection database
mongoose.connect(DB_HOST, dbOptions);
//Store Connection Object
const db = mongoose.connection;
//Connection events
db.once("open", () => {
console.log("Connected to MongoDB database...");
}).on("error", (err: string) => {
console.log(err);
});
//Store session
const sessionStore = new DBSessions({
uri: DB_HOST,
collection: 'sessions'
})
//https://github.com/expressjs/session/issues/633
app.set('trust proxy', 1);
app.use(routesArray,
session({
secret: SESSION,
resave: false,
saveUninitialized: false,
store: sessionStore,
cookie: {
sameSite: false,
maxAge: MAX_AGE,
secure: false,
httpOnly: true
}
})
)
//Starting server
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});

set up mssql-session-store in node.js

I'm trying to use mssql-session-store as nodejs (express) store for session:
https://www.npmjs.com/package/mssql-session-store
This is how it should be configured(from npm page):
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
store: new MssqlStore(options) // see options below
}));
var options = {
connection: existingConnection,
ttl: 3600,
reapInterval: 3600,
reapCallback: function() { console.log('expired sessions were removed);
}
};
My problem is with the options.connection. It should be "Optional instance of a Connection from mssql".
This connection establishment is an async process (from the npm page):
const sql = require('mssql')
async () => {
try {
await sql.connect('mssql://username:password#localhost/database')
const result = await sql.query`select * from mytable where id =
${value}`
console.dir(result)
} catch (err) {
// ... error checks
}
}
This is how express session is being defined in the nodejs initialization:
app.use(session({
name:<session name>,
key: <session key id>,
resave:false,
saveUninitialized:false,
secure: process.env.NODE_ENV ==="production",
secret:<secret string>,
store: new MssqlStore(options), //This is optional - for use when using sql server as a store
cookie:{
//httpOnly: true,
secure: process.env.NODE_ENV ==="production",
expires: config.expressSession.cookieLifeTime
}
}));
The problem is that establishment of the connection is an async process. I've tried several versions to both use the express-session in the application, but doing so just after the connection has been set up (async).
See my basic code (initialization of node.js - servre.js file):
const express = require('express');
const app = express();
const sql = require('mssql');
const session = require ('express-session');
const MssqlStore = require ('mssql-session-store')(session);
var sqlStore = null;
var store = null;
var mssqlConfig =
{
user: <user>
password: <password>,
server: <server name>
database: <database>,
options: {
encrypt: true // Use this if you're on Windows Azure
}
}
I've tried setting the session in the app in the connetion promise:
var sqlConnection = null;
async function getConnectedConnectionOptions()
{
try
{
sqlConnection = await sql.connect(<connection string>);
return await Promise.resolve(sqlconnection: sqlConnection);
} catch (err)
{
sqlConnection = null;
}
}
getConnectedConnectionOptions(),then(result =>
app.use(session({
name:<session name>,
key: <session key id>,
resave:false,
saveUninitialized:false,
secure: process.env.NODE_ENV ==="production",
secret:<secret string>,
store: new MssqlStore(result) ,
cookie:{
//httpOnly: true,
secure: process.env.NODE_ENV ==="production",
expires: config.expressSession.cookieLifeTime
}
}));
but then there's a scope problem where session is not defined in the global app.
Please support.
this is inside example folder in the mssql-session-store module
var dbConfig = {
server: "localhost\\sqlexpress",
database: "sessiontest",
user: "sa",
password: "atonan"
};
var start = function(callback) {
callback = callback || function() {};
sql.connect(dbConfig, function(err) {
if (err) return callback(err);
var app = express();
app.use(session({
secret: '991E6B44882C4593A46C0DDFCA23E06A',
resave: false,
saveUninitialized: false,
store: new MssqlStore({ reapInterval: 10, ttl: 10 })
}));

Resources