Session is not initializing if i run my nodejs server with ip address - mysql

I am using nodejs with express 4 framework. I have setup my node project on server but the problem is that after the login it will not redirect me to dashboard page.
When i check "req.user" after login then it gave me undefined value although its working fine in my local system.
But when i point the ip with domain name then session is initializing successfully. and it redirect me to dashboard page and also gave me req.user information.
This is my session code.
var sessionStore = new SessionStore({}, connection);
// required for passport
app.use(session({
secret: '5372E653ED6BD22E09BF14DE621CAFBFEA8B1391C056B73F3A0FECB31BD4E1B8',
cookie: { maxAge : 2592000000 },
store: sessionStore,
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
app.use(routes);
Route code (after login)
router.all('/user/*', function (req, res, next) {
if (!req.user) {
res.redirect("/login.html");
} else {
next();
}
});
Any Idea?

I think it is intentionally happening in the browser. This doesn't sound like an express issue.
Related issues here:
IP and domain create different session
Why does the session cookie work when serving from a domain but not when using an IP?

Related

/favicon.ico after login in Node JS

I have created a login/register system using express (passport) on my website and I am saving the originalUrl before the user was redirected to the login page but every time after the login, the user is redirected to /favicon.ico instead of the saved Url. Could someone tell me what is the cause of the issue?
My app.use():
app.use((req, res, next) => {
if (!['/login'].includes(req.originalUrl)) {
req.session.returnTo = req.originalUrl;
}
res.locals.currentUser = req.user;
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
next();
})
My /login get and post request:
app.get('/login', (req, res) => {
res.render('login');
})
app.post('/login', passport.authenticate('local', { failureFlash: true, failureRedirect: '/login' }), (req, res) => {
const redirectUrl = req.session.returnTo || '/';
console.log(redirectUrl);
delete req.session.returnTo;
res.redirect(redirectUrl);
})
You have a race condition in your session between two incoming requests.
Your app.use() middleware is going to see the /favicon.ico request and will overwrite the req.session.returnTo value that your login route may have just set. If these two requests come in one immediately after the other (which is likely when a browser first visits your site), then the /favicon.ico route will mess up the session state you just tried to set with the /login route.
I can't tell what that middleware is trying to do, but it looks like it's very capable of overwriting stuff in the session that other requests are in the middle of using. Redirects after login are much, much safer to do by putting the eventual redirect URL in the query parameter. Then it is stateless on the server and isn't subject to these types of race conditions when there is more than one incoming request to the server form the same user.
FYI, you could also fairly easily prevent this particular problem (though not other potential race conditions) by just putting this route handler before your middleware:
// put this before your middleware
app.get("/favicon.ico", (req, res) => {
res.sendStatus(404);
// or instead of a 404, send an actual favicon.ico file
// just don't let routing continue to your middleware
});
This would keep your middleware from running at all when /favicon.ico is requested and thus prevent that specific place that a race condition with your session data is caused.

How to serve index.html file with Apollo Server?

I have this code in index.js:
const PORT = process.env.PORT || 5000;
server.listen(PORT).then({ url }) => {
console.log(`Server running at url: ${url}`);
});
In local development, when I went to localhost:5000 on my browser, I could test with the GraphQL playground.
Now, I just finished deploying with Heroku. When I go to my URL, I see:
GET query missing. I assume this happens because apollo is trying to open the GraphQL playground, but it is blocked in production mode.
How can I tell apollo to serve client/index.html instead?
Note: I tried putting index.html in the root directory as well, but nothing changed.
I saw in a tutorial video that the answer to this question in express is:
app.use(express.static('client'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client','index.html'));
});
I don't know how to do this in Apollo.
The standalone Apollo Server cannot be used for serving static files or exposing other endpoints. If you need this functionality, you need to use an HTTP framework like Express, Hapi or Koa and then use the appropriate Apollo Server integration.
Example using Express:
const server = new ApolloServer({ ... });
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);

404 Error when making a POST request using fetch()

I am following this tutorial from Hakernoon to set up Node.js with MySQL using my machine as local server.
I am using a few different tools, but they don't seem to be a problem. I'm using:
Ubuntu 16.04
Node.js
MySQL Workbench (He uses Homebrew because his is a Mac)
MySQL
knex.js
Express
*(Ubuntu and Workbench are the only differences)
Summarizing,the whole tutorial works well except when I reach the part of 'Login'. Here, we build a form to enter the user name and password making a POST requests. Then, if everything is OK, it returns a 200 status, else shows a message saying the login failed. And here is the problems. Every time I try to log in (even when being sure the credentials are correct and knowing that that user is stored in the database) it tells me that the login fails.
Checking on the browser inspect tool, it shows a Fail to load resources: the server responded with a status of 404 (Not found). It also points out that the problems is in the fetch() function I use in my post function to make the POST requests.
I checked the documentation on fetch() but is does not clarify much. Also I tried to contact the author of the tutorial and I got no answer. What am I doing wrong with fetch to give me the 404 status?
Also, every time I create a new user (also a POST request), it does it with no problem and I can see it in the database in MySQLWorkbench.
This is the file (app.js) with the code to create users and login:
const CreateUser = document.querySelector('.CreateUser')
CreateUser.addEventListener('submit', (e) => {
e.preventDefault()
const username = CreateUser.querySelector('.username').value
const password = CreateUser.querySelector('.password').value
post('/createUser', { username, password })
})
const Login = document.querySelector('.Login')
Login.addEventListener('submit', (e) => {
e.preventDefault();
const username = Login.querySelector('.username').value
const password = Login.querySelector('.password').value
post('/login', {username, password})
.then(({status}) => {
if(status === 200)
alert('login success')
else
alert('login failed')
})
})
function post (path, data) {
return window.fetch(path, { <========= Here is where the browser shows the problem
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
}
***I am not posting the rest of the code to not make it too long, if more info is needed, let me know). Thanks!

Using passport.js and plain SQL query to authenticate

I'm working on a project and I have the following issue.
I want to implement logic for user login with Passport API but I'm having difficulties of understanding how it works, especially the way I want to implement it (with plain SQL queries). I have gone thru several tutorials which explain how this can be done ,but the problem is that in them it is shown only with ORMs, and I do not want it that way. I've wrote a few thousand lines of code so far ,but without success which were deleted after this of course and this is the reason I haven't provided any code below.
I'm using MySQL and Express as frameworks to build the website. If you have any brief or advanced idea of how things can happen I will be happy to hear from you.
Thanks in advance !
Passport can be quite confusing at times, I'll give that to you! I'm assuming based on your question that you want to use the "local" login strategy and not offer something like Google or GitHub Single Sign On. I'll also assume you want to use "Sessions" (cookies) rather than something like JWT.
To do this you'll need to first configure passport with your express app up front. This requires you to initialise passport and a session store (you can use MySQL if you like, or something like Redis).
Then you need to configure your "strategy" which in our cases is the local strategy.
I'll run you through an example with some code that shows how this can be done. I'll shove this all into one code snippet but you may wish to break this out into several files.
Snippet you can clone:
https://gist.github.com/BlueHatbRit/5d07d3f98d41d536a776b74fcb843174
Mirrored here for answer longevity:
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
// Create the express app
const app = express();
// Initialise express-session module effectively deals with serilaising some
// form of ID in a cookie which is secured with the given secret. In this case
// express then remembers this ID in memory. When this cookie is handed
// back to your server, express-session takes that ID and matches it up to
// the data it has stored against that ID in memory. Remember, in production
// you will most probably want to hook this up to some sort of data store,
// either Redis, MySQL, etc...
app.use(session({ secret: "cats" }));
// We need some body parser setup to use Passport with express
// you can checkout the body parser and passport docs to find out why
app.use(bodyParser.urlencoded({ extended: false }));
// Now we initialise passport
app.use(passport.initialize());
// Now setup the session strategy, this happens after the express-session
// initialisation as that must run on a request first. Once we have the data
// from express-session (remember, it converted from a session ID given to
// the user via a cookie, back into the data we stored against the ID) we can
// then pull our any additional information.
app.use(passport.session());
passport.serializeUser(function(user, done) {
// This happens at the end of a request, it recieves the
// req.user object, and you can then choose what to serialise
// into the session (returning the user a new cookie with a
// session ID).
// In most cases you'll want to store as little data as possible
// so just a user.id might be fine.
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
// Assume we stored the user ID in the session in the above
// function call, we can now access it.
// You can now take "id" and pass it into your database and
// get back whatever you want in regards to the user. This may
// just be a small representation of the user, or the entire
// record.
// You can use either SQL or an ORM here. The important bit is
// that you call the "done" callback with whatever object you
// want to represent the user.
User.findById(id, function(err, user) {
// In your main request handlers, you will then call `req.user`
// and get back whatever you passed into the callback.
done(err, user);
});
});
// Now we setup the main "login" route, this will do the first round
// of authentication. It will take a username and password, will check
// those credentails and will then decide whether or not to log the user in.
passport.use(new LocalStrategy(function(username, password, done) {
// Run your SQL here to find the user by their username
// Then check their password is correct
// If something fails then call the "done" callback with a descriptive error
// otherwise call "done" with no error, and pass it the "user" object. This will
// be assigned to req.user which will then later be put through our serialize
// function above.
// In this case I'm using an ORM, but you can use something to execute raw SQL
// if you like.
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
// This is a made up function here, you'll need to create this and fill it out
// if you're using SQL you will probably have a function called "validPassword"
// (not assigned to a user object) where you will then pass in the hashed password
// from your database, and the password they provided you (the password string in this
// case).
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
// We have a user and the passwords match so we can return the user object!
return done(null, user);
}
});
// Now we need to mount our configured strategy to an endpoint
app.post('/login', function(req, res, next) {
passport.authenticate('local', {
successRedirect: '/dashboard', // The user logged in fine, redirect them do the dashboard
failureRedirect: '/login', // The login failed, send them back to the login page
// It is possible to use "connect-flash" here to send back the reason but that's outside of the scope of this
});
});
// Now we'll create some middleware to ensure a user is logged in when trying to access
// a protected endpoint
function protected(req, res, next) {
// req.user will only exist if they've been authenticated
if (!req.user) {
return next(new Error('nice try, but you are not logged in!');
}
return next();
}
app.get('/private-things', protected, function(req, res, next) {
// This code will only be accessible if someone goes to /private-things and
// has a valid session!
console.log(the user is logged in!);
console.log(req.user);
res.sendStatus(200);
});
A warning, I have not run this code. All the code is there though you might spot a few syntax errors and will need to write the SQL to match up to your database.

while using MySql, express, angular, nodejs, will the ports be different for express and node

While looking into express + node + mysql, tutorials suggest to start express server by using node server.js (here server.js contains logic to connect to mysql db), which calls upon app.listen() and angular+node tutorials start node server using npm start.
Are they different and I have to start both?
In case, yes, do I need to use diff ports?
In case, no, how to call upon mysql db? Please give some reference or elaborate.
server.js is as follows:
var express = require("express");
var mysql = require("mysql");
var app = express();
var connection = mysql.createConnection({
host : "localhost",
user : "userid",
password : "password",
database : "sakila"
});
connection.connect(function(error){
if(error) {
console.log("Problem with MySQL"+error);
} else {
console.log("Connected with Database");
}
});
app.use(express.static(__dirname + '/bower_components/angular'));
app.get('/app/#/actors_load',function(req,res){
connection.query("SELECT * from actor",function(err,rows){
if(err) {
console.log("Problem with MySQL"+err);
} else {
res.end(JSON.stringify(rows));
}
});
});
app.listen(8000,function(){
console.log("It's Started on PORT 8000");
});
My phonecatapp has following routers:
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
when('/actors_load', {
templateUrl: 'partials/actors.html',
controller: 'ActorsCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
and controller looks like this:
phonecatControllers.controller('ActorsCtrl',function($scope, $http, $interval){
load_names();
console.log("ActorsCtrl");
/*
$interval(function(){
load_names();
},300);
*/
function load_names(){
$http.get('http://localhost:8000/actors_load').success(function(data){
console.log("kdfhg"+data);
$scope.actors=data;
});
};
});
the partials of html has a link to populate the db data as:
<div>actors</div>
npm install doesn't start a server. It is a command to install packages.
In this particular example the createServer function will accept connection on port 8000. it's taken from node.js docs.
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
As soon as the above code is executed the server is ON. express is a framework for node.js. express creates server on the top of node.js so the express configuration (along with port number) will be executed by node.js. Specified port of express server will run an instance of node.js server, that's the end of the story
To connect to mysql you can use one of the mysql packages for node e.g.:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : '< MySQL username >',
password : '< MySQL password >',
database : '<your database name>'
});
connection.connect();
In above case you are using localhost as a adress of your database.
You can find plethora of mysql packages on npm site: https://www.npmjs.com/search?q=mysql
You may also use mysql.createClient for costumised connection:
var client = mysql.createClient({
user: '??',
password: '??',
port: 8889
});
Note: remember to require your packages otherwise they just simply won't work.
After doing trial and error, I found that srever.js is on server side, angular part of the project is on client side. from angular part, only way to recieve data is using REST API. This role of providing REST API will be facilitated by server.js and hence shall be run on diff port. It means I had to call npm start as well as node server.js. Then I was facing CORS issue, which I resolved by providing
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header ("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
});
in server.js. NOte that to see the effect of this code, you need to start the two servers. This was really a pain point for me. I spent whole day trying various combinations in various places to resolve CORS issue. It seemed not to be working. For some reasons, I stopped the servers and restarted, it was working. After few trials, I realized that even after removing above code, it was working. So, I stopped servers again and this time it was not working, that is how I realized it.
One more thing that I was mingling the two thinking them as one project having client and server side. Any newbie, please understand that client side accesses server side as REST API, so develop them as separate module/project. Do not develop as single module/project.