I'm using cookie-parser, all the tutorial talk about how to set cookie and the time it expiries but no where teach us how to get the value of these cookie
For people that stumble across this question, this is how I did it:
You need to install the express cookie-parser middleware as it's no longer packaged with express.
npm install --save cookie-parser
Then set it up as such:
const cookieParser = require("cookie-parser");
const app = express();
app.use(cookieParser());
Then you can access the cookies from
req.cookies
Hope that help.
First note that Cookies are sent to client with a server request and STORED ON THE CLIENT SIDE. Every time the user loads the website back, this cookie is sent with the request.
So you can access the cookie in client side (Eg. in your client side Java script) by using
document.cookie
you can test this in the client side by opening the console of the browser (F12) and type
console.log(document.cookie);
you can access the cookie from the server (in your case, expressjs) side by using
req.cookies
Best practice is to check in the client side whether it stored correctly. Keep in mind that not all the browsers are allowing to store cookies without user permission.
As per your comment, your code should be something like
var express = require('express');
var app = express();
var username ='username';
app.get('/', function(req, res){
res.cookie('user', username, {maxAge: 10800}).send('cookie set');
});
app.listen(3000);
hope this will help you
const app = require('express')();
app.use('/', (req, res) => {
var cookie = getcookie(req);
console.log(cookie);
});
function getcookie(req) {
var cookie = req.headers.cookie;
// user=someone; session=QyhYzXhkTZawIb5qSl3KKyPVN (this is my cookie i get)
return cookie.split('; ');
}
output
['user=someone', 'session=QyhYzXhkTZawIb5qSl3KKyPVN']
Just want to add that we shouldn't be using modules to do trivial stuff. Modules are very convenient and fast forward development, but keep us from learning by creating infrastructural code.
I'm a professor not a boss so I value more programmers knowledge/skill development than to write code in lesser time without learning anything...
Back to business...
Unless you need signed cookies, or anything more complex, it's perfectly possible to write your own middleware to parse cookies and add the values to the rest of the pipeline as the module does.
app.use((req, res, next) => {
const { headers: { cookie } } = req;
if (cookie) {
const values = cookie.split(';').reduce((res, item) => {
const data = item.trim().split('=');
return { ...res, [data[0]]: data[1] };
}, {});
res.locals.cookie = values;
}
else res.locals.cookie = {};
next();
});
Anywhere you need to read the cookie it's available via res.locals.cookie, conveniently formatted as an object.
You could even add a custom cryptography strategy here to make sure no one is reading your cookie.
Just remember middlewares are ordered, so this one has to be added before any other middleware or route that uses the cookie.
Related
I have been pulling my hair out the last couple of days. No matter how many google searches I make I can't find an answer so I come here as a last resort in hope of some help.
I am creating a full stack application on the MEAN stack. My login works. It is verifying that the email and password is matching a user's email and password in my database. Now I want to send a JWT token to my client so I can keep the user signed inn. I understand how JWT works and I have generated one already
const ACCESS_TOKEN_SECRET = "a random string";
const payload = {"username": login_result[0].username};
const accessToken = jwt.sign(payload, ACCESS_TOKEN_SECRET);
This is where my problems start. I want to store the token in a cookie, to prevent XSS attacks. I have tried all kinds of ways to store the JWT in a cookie. Most forums wrote that I should do
res.cookie('access_token', accessToken);
As I understand, this should automaticly store the JWT in a cookie, on my client, under the name "access_token". However this does not work. When this line is in the code, nothing is happening. By "nothing is happening" I mean that the client code does not execute.
If a password/email is innvalid, I return an error code.
if(res.msg == "403"){
this.showLogErrorMsg = true;
}
This part works.
The else statement looks like this
else{
console.log("Valid username and password");
window.location.href = "http://localhost:4200/profile";
}
Meaning, if the log in is wrong, it will print an error (and it does), if the log in is correct, they are suppose to get redirected. This does not work. It did work when I did
ret.json({"access_token":accessToken});
but does not work with
res.cookie('access_token', accessToken);
This is what I don't understand. It does not store the access_token in cookies and it does not execute the code inside the else statement. There are no error messages on my server or client. Further more, every guide or tutorial says to use the res.cookie, since I am using Express as my webserver.
I have even tried adding the following options:
res.cookie('access_token', accessToken,{domain: domain, path: '/',httpOnly:false,
secure:false,sameSite:false});
The solution is to either, somehow make the res.cookies work, which I really want to do due to it being "what everybody else is using" and it seems really chill. Or, send the JWT token as res.json and then save the token to a cookie in angular. However, does this open you up for XSS? And if not, how can I save something to a cookie in angular?
Thank you guys in advance.
This is a basic express app that sets, unset, and displays cookies.
set GET /login
unset GET /logout
display GET /
This is not dependent on the client (angular)
# main.js
const express = require('express')
const cookieParser = require('cookie-parser')
const app = express()
app.use(cookieParser())
const port = 3000
const accessToken = 'XXXXXXXXXXXXXXXXXXXXX';
app.get('/', (req, res) => {
res.json(req.cookies)
});
app.get('/login', (req, res) => {
res.cookie('access_token', accessToken, { path: '/', httpOnly: true, sameSite: "strict" })
res.send('"access_token" cookies was set !')
});
app.get('/logout', (req, res) => {
res.cookie('access_token', accessToken, { maxAge: 0 })
res.send('"access_token" cookies was unset !')
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
});
const express = require("express");
const app = express();
var i = new Number;
i=0;
app.get("/", function(req, res){
i++
console.log(i);
});
app.listen(8080);
I created a very small node js project. I have a problem. when I create a variable like above, it doesn't evaluate for each user separately. that is, when a user requests a get, I want it to be 1 each time.
Sample
my problem is that when a jack user enters a site, if he doesn't log out, someone who enters the site's home page from another device enters his account with jack.
how can I do that?
The simplest answer for your question is to simply declare and increment the variable inside the function passed to app.get, but I'm going to assume that you would like a situation where, for a given user's series of requests, the number will increment.
The simplest way to do this is using a server side session, which is provided by the express-session library. Additionally, in order for this to work, you need to call res.end() in order to send the cookie associated with the server session back to the user's browser. More information on sessions generally can be found here.
Below is code to replicate the intent of what you have there, but incrementing for each request from a unique browser instance (identified by the same cookie value associated with the server session):
const express = require('express');
const session = require('express-session');
const app = express();
app.use(session({
resave: false,
saveUninitialized: true,
secret: 'secret',
cookie: {
maxAge: 60000
}
}));
app.get('/', function(req, res){
if (!req.session.value) {
req.session.value = 0;
}
req.session.value++;
console.log(req.session.value);
res.end();
});
app.listen(8080);
I am trying to access my session token from other routes after setting it in a route. I am currently unsuccessful. Following the relevant code of the three files.
server.js: It calls the routes thermostats, login and also sets session token.
var session = require('express-session');
var app = express();
app.use(session({secret: 'keyboard cat',cookie: { secure: true }}))
var router = express.Router();
var thermostats = require('./api/routes/thermostats')(router, app, session);
require('./api/routes/login')(router, app, session, thermostats);
login.js: When the user goes to localhost:3000/login/, the login token needs to be saved in the session
module.exports = function(router,app, session, thermostats){
router.get('/login/', function(req, res) {
list(req, res) //response of this function has session which needs to be saved.
console.log(res.session)
app.use(session(res.session)) //trying to save the res.session as session token
});
}
thermostat.js: Needs to access the session token before can display any information.
module.exports = function(router,app){
router.get('/thermostats/', function(req, res) {
console.log(req.session) //Set to default/null values and not the updated session values
});
}
It might be something small but I cannot figure out the issue. I would appreciate any help.
Thank you
Express-session should automatically save the session, based on the configuration.
Looking at the 'resave' config option in the express-session docs:
resave
Forces the session to be saved back to the session store, even if the session was never modified during the request. Depending
on your store this may be necessary, but it can also create race
conditions where a client makes two parallel requests to your server
and changes made to the session in one request may get overwritten
when the other request ends, even if it made no changes (this behavior
also depends on what store you're using).
This is by default, true, so it should already start working without you needing to add app.use(session(res.session).
Edit: You will be able to save to the session by adding fields to the req.session object:
router.get('/login/', function(req, res) {
getDataFromExternalApi(req, function(err, apiResponse) {
var data = apiResponse.data;
req.session.data = data;
// if resave option is true, this should automatically save to the session store after this request is done.
});
});
Generally, you shouldn't be using app.use in your request handlers. Those are generally reserved for setting up the server, as it defines what middleware express uses.
i just want to try basic methods to set cookie and show in request head.
front-end is just a basic html form with username and password text input, use POST method to transfer data.
below is code based on express.
server just receive req.body, then set it as cookie with domain: localhost:1338/base
cookieRouter.js:
var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var router = express.Router();
router.use(bodyParser.urlencoded({ extended: false }));
router.use(cookieParser());
router.get('/', function (req, res) {
res.send('this is a router base page!');
});
router.get('/index1.html', function (req, res) {
res.sendFile(__dirname + '/index1.html');
});
router.post('/index1.html', function (req, res) {
res.cookie('name', req.body, { domain: 'localhost:1338', path: '/base' });
res.send(req.body);
});
module.exports = router;
app.js
var express = require('express');
var app = express();
var cookieRouter = require('./cookieRouter.js');
app.get('/', function (req, res) {
res.send('this is home page!');
});
app.use('/base', cookieRouter);
app.listen(1338);
after run app.js, request header has set-cookie value obviously. but can't get it into request header, and req.cookies is empty object {}, even after refreshing the web.
but if i just use simplest demo, it can work, for instance:
router.get('/', function (req, res) {
res.cookie('name', 'test');
});
one more thing, i feel the trouble with express is that only one res.send(), res.redirect()... can be sent as by default it will add head automatically, otherwise, it will come up with error: Can't set headers after they are sent.
someone said add return can solve this problem, but i failed, so want to how how to add, can anyone give an complete demo?
The cookie is missing because the domain attribute is incorrect -- 'localhost:1338' need to be changed to 'localhost'. Port information should not be included in domain.
Yes, according to the Network panel of browser dev tool, there is a Set-Cookie response header (as the screenshot displayed). However, if you check Application - Cookies panel in Chrome (or corresponding panel in other browsers), you will find that: the cookie specified by Set-Cookie header is not there. Browser does not store it and won't send it in the following HTTP requests.
Also, please note that as the cookie's path is /base, only the HTTP requests whose URL starts with /base can send the cookie.
I set up session management in my node js/ express js website successfully. I stores session data in mongo db. I want the session to be valid for the users who log in for a couple of weeks. The code is as follows:
var cookieParser = require('cookie-parser');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
app.use(cookieParser());
app.use(session({
store: new MongoStore({ mongoose_connection: db }),
secret: 'cookie_secret',
cookie: { maxAge: null }
}));
It works fine for normal users, but my problem is with web crawlers such as google bots and facebook bots. I still want them to crawl my website but I don't want their sessions to be stored in my mongo db. It's taking up lots of space and storage is increasing daily which costs me money.
How to selectively choose which sessions to be stored in the db. I can check for req.headers['user-agent'], but where to use it in my code? How to tell express-session not to store session sometimes?
You can use the session middleware conditionally, based on the User-Agent header. A simple example:
var sessionMiddleware = require('express-session')({
...configuration here...
});
app.use(function(req, res, next) {
var ua = req.get('user-agent');
// If the User-Agent header contains the string "Googlebot",
// skip the session middleware.
if (/Googlebot/.test(ua)) {
req.session = {}; // perhaps a bit too simple?
return next();
}
return sessionMiddleware(req, res, next);
});
It would depend on your actual use of req.session if the code above works, or if you need to mock req.session a bit better (for instance, if you use any of the req.session methods in your code,
you may need to mock those too).