req.cookies :
When using cookie-parser middleware, this property is an object that
contains cookies sent by the request. If the request contains no
cookies, it defaults to {}.
// Cookie: name=tj
req.cookies.name
// => "tj"
This is what i found in the official documentation , However, it is expected that req.cookies.name returns an object contains all info about cookie , Not ONLY STRING which is the value of cookie .
Expected
req.cookies.name ==> {value:"e3Lfdsd3pd1...er",expiration:...,..:...}
Actual
req.cookies.name ==> "e3Lfdsd3pd1...er"
How to retrieve other info of cookies than its value using request object ?
Is there something ready in express or cookie-parse, Or have i to use Nodejs built-in API?
You can not access this data because it's simply not there.
The browser sends only the key-value pairs.
expires and max-age are local informations for the browser only and will not be committed to a web server in general.
You can set those attributes on cookie creation on the server, also you can overwrite them later (e.g. for invalidating), but I'm afraid you can't read the values of those attributes.
Related
Sorry guys, I'm really new to sessions and cookies and I'm trying to understand the mechanism behind it. I wanted to add register/login to my simple website and in order to do I need to understand web authentication and I really think I will have tons of questions regarding this topic.
Initially, I have register page that sends info after clicking submit button to a node server using express.
I'm trying to see what happens, so I've created a session in post route, it's created in the browser (connect.sid), then I commented out the part that creates that session and just tries to redisplay the session object, but it's undefined, but I still can see the session in the browser's cookies section, so what's going on? Thanks
app.use(session({
secret:"my test secret",
cookie:{},
resave:false,
saveUninitialized:false
}))
app.post("/register", (req, res) => {
req.session.usertest = "testsession_hardcodedvaluefornow";
console.log(req.session.usertest); // -> this is okay when above line to create is uncommented
//but when I comment the session assignment, it becomes undefined?
res.send("In register...");
})
I can see the session cookie even after commenting out the create session and posting over and over.
connect.sid s%3A_TahsTv0xhY-iHIdjDRblYJ_aZZ5oiSd.do7JcOGR1FaXPcFFIQ6hg5AW%2B0XVsYwIRO8vndyjDzs
req.session.id produces a different value (not undefined) even if I delete my session in the browser, so not sure where that comes from.
There is no "usertest" key in the session object, therefore it is undefined. The reason it's not undefined when you uncomment that line is because you create that key yourself in that instant with that line.
You can get the whole session object by using req.session, the session id by using req.session.id and the session cookie by using req.session.cookie.
Edit
To further clarify: a session will be made for every connected client. That is why you can see the cookie in the browser. That has no meaning however, it's just a way to uniquely identify that client (without actually telling you who that client is). Any information about that session (whether they're logged in, user id,...) needs to be stored in a session store. Express-session will use memory store by default, if the server restarts all that information will be lost, which is why that key doesn't exist. In order to preserve that information it has to be stored in a persistent session store. More information on session store implementations for express-session and how to use them can be found here: https://www.npmjs.com/package/express-session
As for the cookie values you get, those are the default ones set by express-session since you haven't set any yourself. You can change the maxAge to let it expire (or set it so 10 years or more for a more persistent session), you can specify a domain to which that cookie belongs, you can set it to secure (to only allow it over secure connections, e.g. https) and httpOpnly is by default true. httpOnly cookies cannot be accessed/altered by the client (although you can see them in the browser), do not set this to false.
I am using Node JS with express-session.
One question answered here advises to use req.cookies['connect.sid'] to get the session ID. Another answer suggests I use req.sessionID
When I compare the two the req.cookies['connect.sid'] has a string like the following:
s:G1wOJoUAhhemRQqCs7dAGlMIk5ZGaJUg.z1/HrHTfndRqKpXza8qWuwHLS067xrWfVgqTDDGYoos
req.sessionID has a string like the following:
G1wOJoUAhhemRQqCs7dAGlMIk5ZGaJUg
If the second string is the session ID (G1wOJoUAhhemRQqCs7dAGlMIk5ZGaJUg), what is the other information in the connect.sid cookie?
Tried looking for the answer via google and other websites with no luck.
Thanks,
Darren
express-session stores all session information server-side. If you use an sql database, you'd have a table for your sessions, that would look like this :
sid | sess | expire
R02GJn2GoyaqRyten1BEGbHa0XCbj529 | {"cookie": "originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"mybool":true,"userid":16}
That's the answer to your question, and a short explanation of what the data means, sessionID is just a (primary) key to access the data that is only available server-side.
Now from your question it looks like you're planning on using express-session wrong.
To use express-session on your express server you would include it like so :
const session = require('express-session');
app.use(session({
name : 'mycookie',
secret : 'mysecret',
saveUninitialized : false,
resave : true
}));
and every request that goes into all subsequent routes after this will have a .session attribute. In any case, you should never need to access the session id yourself, the middleware itself authenticates every request against whatever store you used for express-session.
app.get('/givemeasession',function(req,res,next){
req.session.mybool = true;
req.session.somedata = 'mystring';
req.session.evenobjects = { data : 'somedata' };
res.send('Session set!');
});
app.get('/mysession',function(req,res,next){
res.send('My string is '+req.session.somedata+' and my object is '+JSON.stringify(req.session.evenobjects));
});
Bottomline : you shouldn't ever need to access the cookie yourself, or do anything with it, because any cookie auth is automatically handled by the middleware.
The accepted answer is correct by saying, don't handle cookies and sessions by yourself, but I don't think it answers the question:
The second part in connect.sid is the cookie signature.
In case of express-session this is generated by the package cookie-signature with the secret you set when you set up the session middleware.
As you can see in the source-code, the very first step is verifying if the cookie was signed by the secret. Afterwards the cookie is retrieved from the store.
(In case of the memory store, the retrieval also deletes the cookie if expired)
Source: https://github.com/expressjs/session/blob/1010fadc2f071ddf2add94235d72224cf65159c6/index.js#L542
Right now I'm working on a React/Redux full stack application and I'm working on setting up JWT auth and passing the JWT via cookies. I had a couple of questions on handling the CSRF token generated by the server.
1) Once you set the CSRF token on the server side, does it then get passed to the client? How exactly does it get passed? (I've seen examples where its passed in as an object, but the ones ive found weren't explained very well or just scarce)
server.js
// config csrf in server
app.use(csrf({
cookie: {
key: '_csrf',
secure: true,
httpOnly: true,
sameSite: 'strict',
maxAge: 86400
}
}))
// Hits my api routes, and if these arent hit, the index.html file is rendered
app.use(routes)
// Route used to fetch the index html file
app.get('*', (req, res) => {
let csrfToken = req.csrfToken()
console.log(csrfToken) // This doesnt console log anything on the server side
res.sendFile(path.join(__dirname, "./client/build/index.html"), {
_csrf: csrfToken
})
})
2) Once the CSRF token is set, should it be stored in the state of the application (Redux store) for persistent storage? Or would this be unnecessary?
3) On the client side, when I'm ready to submit data to a route via POST request, if I understand correctly, you'd have to include the input hidden field with the csrf variable like so:
<input type="hidden" name="_csrf" value=csrfToken/>
So when you submit a form, you'd include that input, then in the post request (assuming fetch or axios), you'd set the headers to include that csrf token, that way the server can compare it to the token the client is submitting to the route, am I understanding this correctly?
Thank you!
None of what you’ve asked specifically relates to react or redux. This is about request / response exchange with an HTTP server.
When using the the CSRF middleware, it automatically provides a CSRF tokens as a session cookie on request, and you’re expected to provide that back to the server on further requests.
1) CSRF tokens are usually set in a cookie by the server, or set as meta tag in the HTML. This code is generated uniquely per HTTP request to the server. It’s the applications responsibility to read the cookie/meta tag and then send it back to the server for future requests. One possible way is as a header: ‘X-csrf-token’ (https://en.m.wikipedia.org/wiki/Cross-site_request_forgery)
2) unnecessary in some cases: but that’s only by virtue of the fact that if the server sends a cookie header response, then your browser will always store that cookie, unless you have cookies turned off. When sending a request to the server, you need to retrieve that cookie and send it as the header above
3) I suggest you read the readme for express CSRF middleware (https://github.com/expressjs/csurf/blob/master/README.md), particularly this part about how the middleware looks for the CSRF tokens in responses or further requests:
The default value is a function that reads the token from the
following locations, in order: • req.body._csrf - typically generated
by the body-parser module. • req.query._csrf - a built-in from
Express.js to read from the URL query string.
• req.headers['csrf-token'] - the CSRF-Token HTTP request header.
• req.headers['xsrf-token'] - the XSRF-Token HTTP request header.
• req.headers['x-csrf-token'] - the X-CSRF-Token HTTP request header.
• req.headers['x-xsrf-token'] - the X-XSRF-Token HTTP request header.
As you can see - how you provide it back to the server is up to you — most people choose a header, but it can be as a body or a get request query string.
I am trying to set/get cookies for users that browse on my web server, I found the following StackOverflow question: Get and Set a Single Cookie with Node.js HTTP Server and I was able to get the cookie set on the browser just fine. When I go to the cookie viewer I see the cookie I set just as I want it. The problem comes when I try to view the cookies, the request.headers.cookie is always undefined. How would I go about getting the cookies on a users browser, preferably without NPM modules and purely node and its own modules?
How I'm setting the cookie (this works fine, I am able to see this cookie in the browser when I go to view my cookies):
response.writeHead(statusCode, {
'Set-Cookie': cookie
})
// statusCode = 200
// cookie = 'token=SOME_TOKEN'
// In the browser I see the exact cookie I set
How I'm trying to get the cookie (not working always undefined):
let cookies = request.headers.cookie
// This returns undefined always
// even when I can view the cookie in the
// browser the request is coming from
// Also quick note: I'm currently not
// parsing the cookies out to view them as
// a JSON object because I can not get any
// of the cookies
EDIT:
It seems I have finally found the error, it sets the cookie path to be whatever path I set the cookie on, so I was setting the cookie on the "/auth" route. How can I make it so that this cookie is accessible from any route the user goes to?
Ok I finally found the solution, my error was that it was auto-setting the path of the cookie to be "/auth" so I could only access the cookie if the url requested contained "/auth", where I set the cookie I changed it to the following:
response.writeHead(statusCode, {
'Set-Cookie': cookie + '; Path=/'
})
And now I can access my cookie
Have been working through the sails cast tutorials and am confused about the way that sessions work.
In the tutorial, the user is marked as authenticated in the session controller by:
req.session.authenticated = true;
req.session.User = user;
res.redirect('/');
Why is the session being saved in the request?! My understanding is that the 'req' object in express.js is the information the browser sends to the server.
Shouldn't the server save this information elsewhere (won't the request object be deleted when theres another request?)
Furthermore, somehow the application retrieves the authentication status from another object session when templating a page with ejs:
<% if (session.authenticated) { %>
why isn't this variable set directly?
Probably a silly question but I am confused at how the logic works and online articles/tutorials aren't helping me understand...
It is common practice for express middleware (remember, Sails is built on express) to attach properties to the req object so it may be accessed in later middleware, and eventually your controllers. What happens behind the scenes is your req object comes in with a cookie containing the session ID, and then the session middleware uses that to retrieve the actual session data from some datastore (by default, and in-memory store is used. Super fast and easy for development, but not recommended for deployment), and then attaches that to the req object.
Regarding the value of session.authenticated in your EJS, by default Sails includes req.session in res.locals (accessible in views), so that value will be whatever is stored in the session via your controller.
The browser sends over the session id which is stored on a cookie. The session object is referenced by that session id which is stored server side. The session is attached to the request (for convenience I suppose). You can read more here https://github.com/expressjs/session#compatible-session-stores
I wouldn't know what is setting session.authenticated without seeing more code.