Localhost accessed req.session.userid but virtual host can't be reached - javascript

here is some problem that i have... i have been tried days to figure it out but nothing make it working.
i have Node.js Express session on backend and there are users, when i make login i set req.session.userId = "userid" and i have middleware that check if req.session.userId exist and then next() so on Localhost everything worked fine but when i hosted my website i can’t access the req.session.userId it's mean the Middleware don’t next()
Frondend hosted: Netlify
Backend hosted: Nodechef
Mysql hosted: Nodechef
i don’t know, maybe i missed something or that i have to made some
changes when hosting...
i hope you guys have solution for me 🙌🏻
index.js
const express = require('express');
const cookieParser = require("cookie-parser");
const session = require('express-session');
const cors = require('cors');
const app = express();
app.use(express.json());
app.use(cookieParser());
app.use(cors({
origin: '***********',
credentials: true
}));
app.all('/', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Credentials", true);
next();
});
app.use(session({
secret: "******",
name: "*****",
saveUninitialized: true,
resave: true,
cookie: {
domain: '*******',
secure: true,
maxAge: 1000 * 60 * 60 * 24 * 365,
}
}))
app.get('/', (req, res) => {
res.send({ msg: "seccess" })
})
app.use('/users', require('./routes/users'))
const PORT = 3000
app.listen(process.env.PORT || PORT, () => {
console.log(`Express server listening on port ${PORT} `);
});
users/login
const router = require('express').Router()
router.post('/login', (req, res) => {
const { userEmail, userPassword } = req.body
db.query(`SELECT * FROM users WHERE userEmail = ?`, userEmail,
(err, result) => {
if (err) {
return res.send({ err: err })
} else {
if (!userEmail || !userPassword)
req.session.userId = user.id
res.send({ msg: "Login Succes", req: req.session, user: user.id })
}
})
});
Middleware
module.exports.onlyLoggedUsers = (req, res, next) => {
if (req.session.userId) {
next()
} else {
res.status(200).send({err:"sensetive content for logged users only, plesae log in"})
}
}

I just added app.enable('trust proxy')
and it is work temporarily, in safari this not work and also on smartphone, if I got to setting in safari and turn of Prevent Cross-Site Tracking it is working so my question is how I can run the application without turn of Prevent Cross-Site Tracking.

Related

req.isAuthenticated is not a function while using Express and passport

in the last few hours I setup a backend express server. It works just fine and now I tryed to implement an authorization with help of a tutorial.
The login works, but when I try to open /authrequired (so basically a future page which needs a logged in user to work) I get the error message: "TypeError: req.isAuthenticated is not a function"
Here is my index.js file:
const express = require('express');
const fs = require('fs');
const http = require('http');
const https = require('https');
const path = require('path');
const uuid = require('uuid').v4;
const session = require('express-session');
const FileStore = require('session-file-store')(session);
const bodyParser = require('body-parser');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const users = [
{id: '2f24vvg', email: 'test#test.com', password: 'password'}
]
// configure passport.js to use the local strategy
passport.use(new LocalStrategy(
{ usernameField: 'email' },
(email, password, done) => {
console.log('Inside local strategy callback')
// here is where you make a call to the database
// to find the user based on their username or email address
// for now, we'll just pretend we found that it was users[0]
const user = users[0]
if(email === user.email && password === user.password) {
console.log('Local strategy returned true')
return done(null, user)
}
}
));
// tell passport how to serialize the user
passport.serializeUser((user, done) => {
console.log('Inside serializeUser callback. User id is save to the session file store here')
done(null, user.id);
});
passport.deserializeUser((id, done) => {
console.log('Inside deserializeUser callback')
console.log(`The user id passport saved in the session file store is: ${id}`)
const user = users[0].id === id ? users[0] : false;
done(null, user);
});
const app = express();
app.enable('trust proxy')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(session({
genid: (req) => {
console.log('Inside the session middleware')
console.log(req.sessionID)
return uuid() // use UUIDs for session IDs
},
store: new FileStore(),
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
app.use(passport.session());
app.post('/login', (req, res, next) => {
console.log('Inside POST /login callback')
passport.authenticate('local', (err, user, info) => {
console.log('Inside passport.authenticate() callback');
console.log(`req.session.passport: ${JSON.stringify(req.session.passport)}`)
console.log(`req.user: ${JSON.stringify(req.user)}`)
req.login(user, (err) => {
console.log('Inside req.login() callback')
console.log(`req.session.passport: ${JSON.stringify(req.session.passport)}`)
console.log(`req.user: ${JSON.stringify(req.user)}`)
return res.send('You were authenticated & logged in!\n');
})
})(req, res, next);
})
function isAuthenticated (req, res, next) {
if (req.session.user) next()
else next('route')
}
app.get('/authrequired', isAuthenticated, function (req, res) {
res.send('you hit the authentication endpoint\n')
})
app.use(express.static(path.resolve(__dirname, 'build')));
app.use(express.json());
// Redirect from http port to https
http.createServer(function (req, res) {
res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(80,433) + req.url });
console.log("http request, will go to >> ");
console.log("https://" + req.headers['host'].replace(80,433) + req.url );
res.end();
}).listen(80, () => console.info('Listening on port', 80))
//Start https server
https.createServer({
key: fs.readFileSync('./ssl/privkey.key'),
cert: fs.readFileSync('./ssl/cert.cer'),
keepAlive: true
}, app).listen(443, () => console.info('Listening on port', 443));
Anyone got a clue? I saw similar questions on stackoverflow, but nothing worked for me.
There is no such function isAuthenticated. That's why you get the error.
Try replace it with if(req.session.user) {
Or by the example in express-session
// middleware to test if authenticated
function isAuthenticated (req, res, next) {
if (req.session.user) next()
else next('route')
}
app.get('/', isAuthenticated, function (req, res) {
// this is only called when there is an authentication user due to isAuthenticated
res.send('hello, ' + escapeHtml(req.session.user) + '!' +
' Logout')
})
EDIT: You also need to use passport session middleware, by adding
app.use(passport.session());
Make sure it is coming after the session init.

Every API request makes 2 new Express Sessions, only keeping the second one for passing to the router once (MongoDB, Express Sessions, Node,Javascript

Im trying to initialize an express session to a Mongo store in my MERN application for passing a user's ID to my passport authentication flow, however it acts unaccordingly to how it should by my understanding.
For each request i make to my auth.routes.cjs, the app makes a completely new session disregarding the currently already initialized one, then makes ANOTHER one, and only the last one gets passed to the router/controller.
I've currently attached a console.log(req.session) to both my index.cjs and auth.routes.cjs for every function called, to get an overview of how and which data is being created and passed between the components.
Index.cjs passes a value of req.session.test='test', then logs session id and session
auth.routes.cjs changes req.session.test to 'test2', then logs session, but only for the second initialization, making it useless
this is what my terminal logs after a request
index.cjs
var FfmpegCommand = require('fluent-ffmpeg');
var command = new FfmpegCommand();
const rateLimit = require('express-rate-limit');
const fs = require('fs');
const passport = require('./middleware/passportInitialization.cjs');
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const fileUpload = require('express-fileupload');
const session = require('express-session');
const { v4: uuidv4 } = require('uuid');
const MongoDBStore = require('connect-mongodb-session')(session)
const store = new MongoDBStore({
uri: process.env.MONGODB_URI,
databaseName: 'test',
collection: 'sessions'
});
store.on('error', function (error) {
console.log(error);
});
const app = express()
const port = 4000;
const db = require("./models/index.cjs");
const Role = db.Role;
const uri = process.env.MONGODB_URI;
app.use(passport.initialize());
app.use(express.urlencoded({ extended: true }));
db.mongoose
.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("Successfully connect to MongoDB.");
initial();
})
.catch(err => {
console.error("Connection error", err);
process.exit();
});
app.use(session({
genid: () => {
return uuidv4() // use UUIDs for session IDs
},
secret: 'wdaoijiuwaheh23n4n23irfu9sujn398fhfmIUQHIG4bhyh9h',// TODO: change this to a random env string
store: store,
resave: false,
saveUninitialized: false,
cookie: {
secure: false,
maxAge: 1000 * 60 * 60 * 24,
sameSite: 'none'
}
}));
app.use(function (req, res, next) {
req.session.test = "test";
console.log('req.session', req.session.id);
console.log(req.session)
next();
});
var filter = require('content-filter');
app.use(filter());
app.use(fileUpload({
createParentPath: true
}));
const corsOptions ={
origin:'http://localhost:4001',
credentials:true, //access-control-allow-credentials:true
optionSuccessStatus:200
}
app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan('dev'));
app.use(express.json());
app.use('/uploads', express.static('uploads'));
require('./routes/auth.routes.cjs')(app)
require('./routes/user.routes.cjs')(app)
require('./routes/upload.routes.cjs')(app)
app.use(function (req, res, next) {
req.session.test = "test";
next();
});
auth.routes.cjs
const verifySignUp = require("../middleware/verifySignUp.cjs");
const controller = require("../controllers/auth.controller.cjs")
const passport = require('../middleware/passportInitialization.cjs');
const authJwt = require("../middleware/authJwt.cjs");
module.exports = function(app) {
app.use(function(req, res, next) {
req.session.test = "test2";
console.log(req.session.id)
console.log (req.session)
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4001');
//res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
//res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader(
"Access-Control-Allow-Headers",
"x-access-token, Content-Type, Accept"
);
next();
});
app.post("/api/auth/refreshtoken", controller.refreshToken);
app.post(
"/api/auth/signup",
[
verifySignUp.checkDuplicateUsernameOrEmail,
verifySignUp.checkRolesExisted
],
controller.signup
);
//endpoint named /api/auth/signin calls the controller.signin function and then saves the user id to the session
app.post("/api/auth/signin", controller.signin);
app.get("/api/auth/google",[authJwt.verifyIfUserIsLoggedIn], passport.authenticate('youtube', {display: 'popup', failureMessage: true, failureRedirect: '/login'}
));
//endpoint with access-control-allow-origin: *
app.get("/api/auth/google/callback", passport.authenticate('youtube', {failureMessage: true, failureRedirect: '/login'}), function(req, res) {
// Successful authentication, redirect home.
const userYoutubeData = req.userYoutubeData;
console.log('userYoutubeData', userYoutubeData);
console.log('shall be linked to user id ' + req.session);
res.header(
"Access-Control-Allow-Origin", "*"
);
res.redirect('http://localhost:4001/upload');
//res.json({message:"Success", username: req.user.username});
});
}
I've been stuck on this for the past two weeks with no luck whatsoever. Hoping that someone could give me insight on my possibly misinterpreted logic behind this flow.

How to configure an SSL certificate for an application that runs in Express?

I'm trying to configure the Express server I have created, to pass the SSL certificate and go from http to https.
I read the Express documentation but I can not find the solution. They proposed things to me like Lets Encrypt but it does not support Node.js I do not know if I should modify the hosts file, which I already modified to run the application, or what I have to do. I saw a form, but it only works on Unix system. I show the way in which I have configured the file of the server in case they can help me, it took three days looking for ways to do it without success. The ones I saw do not support Node.js. Thank you
I EDIT THE QUESTION:
Sorry for not including more details, the question is that my application is not in production and my domain is provisional: michaelgram.test. I think that with that Lets Encrypt does not grant me the certificates. I do not know what else to do.The issue is that the application is hosted locally, on my computer
I edit again:
Forgive, forget to say that my purpose is to create the certificate for an application in which you can make the registration to Facebook and tried the methods that my colleagues kindly offered, but it did not work, thanks to the new facebook policy.
If you have another idea, then my domain would be michaelgram.test
thank you and forgive the inconvenience, for not doing well the question.
let express = require('express');
let aws = require('aws-sdk');
let multer = require('multer');
let multerS3 = require('multer-s3');
let ext = require('file-extension');
let cookieParser = require('cookie-parser');
let bodyParser = require('body-parser');
let expressSession = require('express-session');
let passport = require('passport');
let michaelgram = require('michaelgram-client');
let auth = require('./auth')
let config = require('./config');
let port = process.env.PORT || 5050;
let client = michaelgram.createClient(config.client);
let s3 = new aws.S3({
accessKeyId: config.aws.accessKey,
secretAccessKey: config.aws.secretKey
});
let storage = multerS3({
s3: s3,
bucket: 'michaelgram',
acl: 'public-read',
metadata: function (req, file, cb) {
cb(null, { fieldName: file.fieldname })
},
key: function (req, file, cb) {
cb(null, +Date.now() + '.' + ext(file.originalname))
}
});
let upload = multer({ storage: storage }).single('picture');
let app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(expressSession({
secret: config.secret,
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.set('view engine', 'pug');
app.use(express.static('public'));
passport.use(auth.localStrategy);
passport.use(auth.facebookStrategy);
passport.deserializeUser(auth.deserializeUser);
passport.serializeUser(auth.serializeUser);
app.get('/', function (req, res) {
res.render('index', { title: 'Michaelgram' });
})
app.get('/signup', function (req, res) {
res.render('index', { title: 'Michaelgram - Signup' });
})
app.post('/signup', function (req, res) {
let user = req.body;
client.saveUser(user, function (err, usr) {
if (err) return res.status(500).send(err.message)
debugger
res.redirect('/signin');
});
});
app.get('/signin', function (req, res) {
res.render('index', { title: 'Michaelgram - Signin' });
})
app.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/signin'
}));
app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' }));
app.get('/auth/facebook/callback', passport.authenticate('facebook', {
successRedirect: '/',
failureRedirect: '/signin'
}));
function ensureAuth (req, res, next) {
if (req.isAuthenticated()) {
return next()
}
res.status(401).send({ error: 'not authenticated' })
}
app.get('/api/pictures', function (req, res, next) {
let pictures = [ ];
setTimeout(function () {
res.send(pictures);
}, 2000)
});
app.post('/api/pictures', ensureAuth,function (req, res) {
upload(req, res, function (err) {
if (err) {
return res.send(500, "Error uploading file");
}
res.send('File uploaded');
})
})
app.get('/api/user/:username', (req, res) => {
const user = {
username: 'miguelito',
avatar: '',
pictures: [ ]
}
res.send(user);
})
app.get('/:username', function (req, res) {
res.render('index', { title: `Michaelgram - ${req.params.username}` });
})
app.get('/:username/:id', function (req, res) {
res.render('index', { title: `Michaelgram - ${req.params.username}` });
})
app.listen(port, function (err) {
if (err) return console.log('Hubo un error'), process.exit(1);
console.log('Michaelgram escuchando en el puerto 5050');
})
When you're securing a web server with TLS you need two things:
private_key
server_certificate
To your first point, Lets Encrypt is a service that will support exactly what you're trying to do. The service they provide allows you to generate a trusted key and certificate which secures traffic on the server AS WELL AS let's others know that it was signed by a trusted cert authority. See https://letsencrypt.org/how-it-works/
If you JUST want tls you can generate a self signed certificate like so:
https://www.akadia.com/services/ssh_test_certificate.html
After you have your certificate and your key here is the https configuration for the server:
var https = require('https');
var fs = require('fs');
var express = require('express');
var options = {
key: fs.readFileSync('/etc/apache2/ssl/server.key'),
cert: fs.readFileSync('/etc/apache2/ssl/server.crt'),
requestCert: false,
rejectUnauthorized: false
};
var app = express();
var server = https.createServer(options, app).listen(3000, function(){
console.log("server started at port 3000");
});
See: create a trusted self-signed SSL cert for localhost (for use with Express/Node)
Once you have your key and crt ready you just launch the app with reference to them. These names just came using letsencrypt's default naming.
var options = {
key: fs.readFileSync(__dirname + '/components/ssl/privkey.pem'),
cert: fs.readFileSync(__dirname + '/components/ssl/fullchain.pem')
};
server = require('https').createServer(options, app);

req.user is unidentified in session (Node, express, session, passport)

For some reason req.user is undefined, and after 4+ hours of trying to figure out why, I'm asking here. I even copy-pasted the server/index.js file of a friend's server, changed the auth strategy so it worked for mine, and I get the same issue.
Everything else is working. It redirects to auth0, comes back to the correct place, either creates a new user in the DB or finds the user. In passport.serializeUser it has all the data I passed along. But when I hit the '/auth/me' endpoint, req.user is undefined.
server/index.js
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors')
const session = require("express-session");
const passport = require('passport');
const Auth0Strategy = require('passport-auth0');
const massive = require('massive');
const axios = require('axios');
const process = require("process");
const moment = require('moment');
const app = express();
//app.use(express.static(__dirname + './../build'));
app.use(bodyParser.json());
app.use(cors());
app.use(session({
secret: process.env.SECRET,
cookie: { maxAge: 60000 },
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
// Use the session middleware
massive(process.env.CONNECTION_STRING)
.then( (db) => {
console.log('Connected to Heroku')
app.set('db', db);
}).catch(err=>console.log(err))
passport.use(new Auth0Strategy({
domain: process.env.AUTH_DOMAIN,
clientID: process.env.AUTH_CLIENT_ID,
clientSecret: process.env.AUTH_CLIENT_SECRET,
callbackURL: process.env.AUTH_CALLBACK
}, (accessToken, refreshToken, extraParams, profile, done) => {
const db = app.get("db");
const userData = profile._json;
db.find_user([userData.identities[0].user_id]).then(user => {
if (user[0]) {
return done(null, user[0]);
} else {
db.create_user([
userData.given_name,
userData.family_name,
userData.email,
userData.identities[0].user_id
])
.then(user => {
return done(null, user);
});
}
});
}))
passport.serializeUser( (user, done) => {
//console.log('serializeuser', user)
done(null, user);
})
passport.deserializeUser( (id, done) => {
app.get("db").find_session_user([id])
.then(user => {
console.log(user);
done(null, user[0]);
});
})
app.get('/auth', passport.authenticate('auth0'));
app.get('/auth/callback', passport.authenticate('auth0', {
successRedirect: process.env.SUCCESS_REDIRECT
}))
app.get('/auth/me', (req, res) => {
console.log('auth/me endpoint hit')
console.log(req.user)
if(!req.user){
return res.status(401).send('No user logged in.');
}
return res.status(200).send(req.user);
})
app.listen(process.env.PORT, () => console.log(`Listening on port: ${process.env.PORT}`));
server/.env
CONNECTION_STRING=postgres:*****
SECRET=*******
AUTH_DOMAIN=****.auth0.com
AUTH_CLIENT_ID=***
AUTH_CLIENT_SECRET=***
AUTH_CALLBACK=http://localhost:8084/auth/callback
SUCCESS_REDIRECT=http://localhost:3000/
PORT=8084
Try moving the app.get('/auth', passport.authenticate('auth0')); line after the app.get('/auth/me', (req, res) => { block. app.get can do regex matches and goes with the first one that matches (http://expressjs.com/en/api.html#path-examples), and I think it's trying to run the /auth logic for the /auth/me path.

Can't access cookie on http in Heroku only https

I am having a strange issue with cookies in my node app. It is hosted on Heroku and I use JSON Web Tokens stored in a cookie that is authenticated by my express middleware. When I login on my Macbook pro, the cookie is successfully stored. However, when I use Linux Mint desktop, or an Android tablet, the site logs in but then redirects on protected routes and the cookie is never set.
This is where the cookie is set on login:
let token = jwt.sign({
username: user.username,
email: user.email
}, config.privateKey, {
expiresIn: '7d'
});
let userResponse = {
success: true,
message: 'Successfully logged in!',
id: user._id,
email: user.email,
username: user.username
}
// set cookie for 7 days
res.cookie('auth_token',
token,
{maxAge: 604800000, path: "/"}).json(userResponse);
Here is my server.js file:
'use strict';
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const env = process.env.NODE_ENV || "development";
const mongoose = require('mongoose');
const cookieParser = require('cookie-parser');
const config = require('./app/config/config.js');
process.env.PWD = process.cwd();
// Establish connection with MongoDB
mongoose.connect(config.db.connectString);
app.use(cookieParser());
// Allowing X-domain request
var allowCrossDomain = function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Cache-Control");
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
};
app.use(allowCrossDomain);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static('public'));
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error: '));
db.once('open', () => {
console.log('Connected to sondage database');
});
// ===== Import Routers ======
const userRouter = require('./app/routes/user.routes')(express, app);
const pollRouter = require('./app/routes/poll.routes')(express, app);
const authRouter = require('./app/routes/auth.routes')(express, app);
app.use('/api/users', userRouter);
app.use('/api/polls', pollRouter);
app.use('/api/', authRouter);
// For all other requests, use React Router
app.get('*', function (request, response){
response.sendFile(process.env.PWD + '/public/index.html');
});
app.listen(process.env.PORT || 3000, () => {
console.log('Server running');
});
EDIT I have traced this down to a http vs https issue. If I use https in the request, the cookies work. Otherwise cookies aren't set. So I need a way to force the user to do HTTPS.
I was able to fix this using the heroku-ssl-redirect node package. This takes requests and forces the browser to use https for each request.

Categories

Resources