hapijs / yar Goto Github PK
View Code? Open in Web Editor NEWA hapi session manager
License: Other
A hapi session manager
License: Other
if i set request.yar.set('user', {'a': 'b'});
is that mean every request(from different client) use the same user? isn't each request namespace individual?
TypeError: Uncaught error: request.yar.get is not a function
Steps to replicate:
Start a memcached server
Replace https://github.com/hapijs/yar/blob/master/examples/index.js#L4 with the following:
var server = new Hapi.Server(process.env.PORT || 8080, {
cache: {
engine: require('catbox-memcached'),
host: '127.0.0.1',
port: 11211
}
});
Start the example script
Access http://localhost:8080/set
Expected response: a redirection to /
Actual response: the response body is simply the characters: true
This seems to be an issue with the catbox-memcached
module only. By replacing memcached with redis, everything works as expected:
var server = new Hapi.Server(process.env.PORT || 8080, {
cache: {
engine: require('catbox-redis'),
host: '127.0.0.1',
port: 6379
}
});
I have some troubles with my unit tests in a very specific setup. I have prepared a gist to illustrate the issue: https://gist.github.com/chmanie/8942216
This test run with mocha should fail with the error: Error: expected 400 to equal 200
, but instead it times out.
This issue appears only under the given circumstances. If the Joi validation passes, the test does not time out. I am also not experiencing any timeouts when making an http-request to the live server. If I do not include yar, it also works (!), so maybe it is a problem with it.
I really can not make any sense out of this. Since this might be not an uncommon case I am reporting it here.
When I use Cookie Authentication, I'm confused how to get the signed in user info. Whether the internals.users could be stored in yar? If so, how can I make the data in yar expired?
Like the example : https://github.com/spumko/hapi/blob/master/examples/cookie.js
internals.validateCookie = function (session, callback) {
var password = internals.users[session.id].password;
callback(password === session.password ? null : new Error('Invalid credentials'), null);
};
Thanks for your time!
i can't describe it properly at the moment, but there is a short description to reproduce the error:
setup yar and open your browser. when you have a cookie set, change the cookie password and try to refresh the page.
the error is in yar/lib/index.js on line 181 (cannot read property _isModified of undefined)
edit:
there should be a proper errorhandling if the passwort gets changed. otherwise the app crashes and the only way is to clear the cookies in the browser. and because i'm not able to communicate that at that moment, this is (in my opinion) a really bad behaviour.
Hi nice project but there are some things I do not fully understand
I'm thinking to use yar as a pure session implementation with Redis as the session backend cache.
(by the way if I use yar as a pure session, does it store the sesssion ID in the cookie? and does it sign the session ID?)
Thanks in advance
EDIT: Pure session = maxCookieSize: 0
After changing the authenticated cookie password, restarting the app results in a {"statusCode":400,"error":"Bad Request","message":"Invalid cookie value"} response from the server. But after a refresh of the page, the proper page displays instead of the 400. I have set clearInvalid to true inside the cookieOptions as shown below:
server.register({
register: require('yar'),
options: {
cookieOptions: {
password: 'pass',
clearInvalid: true,
isSecure: false
}
}
}, function (err) {});
I am using Hapi version 8.0.0 and yar version 3.0.3
This issue was started by me over here: https://github.com/spumko/travelogue/issues/34
I now believe the issue to be in yar, so I brought it over here.
I think this strict stale cookie comparison, based on plugin registration time, is causing some issues with clusters -- which I imagine each generate slightly different registration times.
https://github.com/spumko/yar/blob/master/lib/index.js#L55
In my case, I was trying to keep a persistent Passport login across my workers. I would typically get logged in, and as long as I only encountered a single worker, things would be fine. As soon as another worker came in, however, my session got reset.
I removed the comparison above, and it began working as expected.
I looked over the Connect session code, and they appear to be offering various expiry strategies, which might work better in this case.
https://github.com/senchalabs/connect/blob/master/lib/middleware/session.js#L258-L263
I'm a bit confused. Yar's implementation of the cache object, is documented as catbox compatible, but the code does not pass a catbox id object.
yar implementation of the id: https://github.com/spumko/yar/blob/master/lib/index.js#L62
catbox id object: https://github.com/spumko/catbox/blob/master/README.md#api
documentation that says yar is catbox compatible: https://github.com/spumko/yar#options
Code I'm using:
// session cache
sessionCache = new Catbox.Client({
engine: 'redis'
, partition: 'session'
})
sessionCache.start()
server.pack.allow({ext: true})
.require({
yar: {
cookieOptions: {
password: 'secret'
, isSecure: false
, clearInvalid: true
}
, name: 'session'
, store: sessionCache
, ttl: 1000 * 60 * 60 * 24 * 7 // 1 week cache
}
}, function(err){
if (err) throw err
})
Hapi versions <14.0.0 (13.5.3 specifically) shrinkwrap statehood to <4.1.0
So after having added the isSameSite
parameter as a default (#102), statehood
will throw the following error because extraneous properties are not allowed in its config:
[1] "isSameSite" is not allowed
at Object.exports.process (./testing/node_modules/hapi/node_modules/joi/lib/errors.js:152:19)
at internals.Any._validateWithOptions (./testing/node_modules/hapi/node_modules/joi/lib/any.js:661:27)
at root.validate (./testing/node_modules/hapi/node_modules/joi/lib/index.js:103:23)
at root.attempt (./testing/node_modules/hapi/node_modules/joi/lib/index.js:132:29)
at root.assert (./testing/node_modules/hapi/node_modules/joi/lib/index.js:127:14)
at internals.Definitions.add (./testing/node_modules/hapi/node_modules/statehood/lib/index.js:71:9)
at internals.Plugin._applyChild (./testing/node_modules/hapi/lib/plugin.js:584:19)
at internals.Plugin.state (./testing/node_modules/hapi/lib/plugin.js:548:10)
at Object.exports.register (./testing/node_modules/yar/lib/index.js:45:12)
at Object.target [as register] (./testing/node_modules/hapi/node_modules/joi/lib/object.js:79:30)
To reproduce:
// registerYarTest.js
const yar = require('yar');
const Hapi = require('hapi');
const server = new Hapi.Server();
server.connection();
server.register(yar, {})
.then(() => console.log('Success!'))
.catch(err => console.log(err)); // Rejection
npm install [email protected] [email protected]
node registerYarTest.js
Suggested resolution: Remove [email protected] from npm and publish as 8.0.0. As well as removing support for Hapi < 14.
The readme suggests a ternary check for the set environment with an inverse boolean return. I am suggesting to replace the ternary with the negated condition.
Why can I not use flash messages with error objects ? Other types work as expected, is there any limitation about this ?
request.session.flash("error", new Error("test"));
request.session.flash("error"); // gives empty array.
I got a couple errors when trying to implement yar with hapi 3.0.x. I'll submit a pull request with a small update to the readme after I submit this issue.
My original code with examples from original readme:
var Hapi = require('hapi');
var server = Hapi.createServer('localhost', 8000);
var options = {
cookieOptions: {
password: 'password',
isSecure: false
}
};
server.pack.allow({ ext: true }).require('yar', options, function (err) {});
var handler1 = function () {
this.session.set('example', {
key: 'value'
});
return this.reply();
};
var handler2 = function () {
var example = this.session.get('example');
this.reply(example.key); // Will send back 'value'
};
server.route([
{
method: 'GET',
path: '/hello',
handler: function (request, reply) {
reply('hello world');
}
},
{
method: 'GET',
path: '/yar-set',
handler: handler1
},
{
method: 'GET',
path: '/yar-get',
handler: handler2
}
]);
server.start(function () {
console.log('Server started at: ' + server.info.uri);
});
I got this error when trying to run the above code:
C:\...\server.js:11
server.pack.allow({
^
TypeError: Object [object Object] has no method 'allow'
at Object.<anonymous> (C:\...\server.js:11:13)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:902:3
My updated code that seems to work:
var Hapi = require('hapi');
var server = Hapi.createServer('localhost', 8000);
var options = {
cookieOptions: {
password: 'password',
isSecure: false
}
};
server.pack.require('yar', options, function (err) {});
var handler1 = function (request, reply) {
request.session.set('example', {
key: 'value'
});
return reply();
};
var handler2 = function (request, reply) {
var example = request.session.get('example');
reply(example.key); // Will send back 'value'
};
server.route([
{
method: 'GET',
path: '/hello',
handler: function (request, reply) {
reply('hello world');
}
},
{
method: 'GET',
path: '/yar-set',
handler: handler1
},
{
method: 'GET',
path: '/yar-get',
handler: handler2
}
]);
server.start(function () {
console.log('Server started at: ' + server.info.uri);
});
Hi,
I wanted to know what's the best way to handle yar.get errors, here's my code:
const indexHandler = (request, reply) => {
var userStatus = request.yar.get('authenticated').key;
reply.view('./pages/index', {
title: "Home",
isAuthenticated: userStatus
})
}
The first requests it throws a 500 error since it cannot get the key/value from redis, do I have to do a try catch and set value of userStatus to false only the first time, or is there a specific way to handle those errors with yar?
Thanks.
Don't use ^ in package.json unless the code will not work with n.x.x instead. Basically, ^ means you rely on a change in a minor revision. It is not correct to just use it to force the latest and greatest if you don't require it.
Hi guys,
just one small question. I have a server running which listens on 2 different urls. I'm using yar for my sessions. But it's critical to use the respective domain for cookies depending on where the request comes from. I can see that you setup your domain used for cookies in your configuration object. So, is it possible to assign this per request? Or is it something related to hapijs?
Hello,
I'm facing issue related to the session time out. When a request with cookie which is already expired is sent, the server responds well and it seems there is no server-side check if the cookie is expired.
I know the browsers check the expiration date and the max age parameter and if the cookie is not valid, it will not be added to the headers, but it is strange to me the server has no validation on that.
Both myself and some others are having a hard time understanding why express-session
hashes the session ID cookie.
The current maintainer of express-session
inherited the repository and while he has some justification as to why the library hashes the session ID, he is not certain why is predecessor did it.
He suggested that I ask here as your library seems to do something similar.
The comments and answers on this Information Security question seem to think it is unnecessary so long as your session ID is long and your random-number generation is unpredictable. Does this sound accurate to you?
I understand full well that express-session
is not your responsibility but I am hopeful that you can help us understand why session middleware hashes/signs the cookie. What kind of attacks does it defend against?
Hi, i'm new on this so perhaps there is some basic rule about communication i'm losing. I don't found a best place to ask.
So i made a basic ajax call from client side from a server 1:
$(document).ready(
function(){
console.log(jQuery.support.cors); //true
url: "http://127.0.0.1:3002/a",
xhrFields: {withCredentials: true},
success: function(data){console.log(data)}
});
$.ajax({
url: "http://127.0.0.1:3002/b",
xhrFields: {withCredentials: true},
success: function(data){console.log(data)}
});
}
);
and I created a basic server 2:
var Hapi = require('hapi');
var server = Hapi.createServer('0.0.0.0', 3002, { cors: { credentials: true }});
var options = {
cookieOptions: {
password: 'password',
isSecure: false
}
};
server.pack.allow({ ext: true }).require('yar', options, function (err) { });
server.route({
method: 'GET',
path: '/a',
handler: function(req) {
req.session.set('example', { key: 'value' });
console.log(req.session.id);
req.reply('a');
}
});
server.route({
method: 'GET',
path: '/b',
handler: function(req) {
var example = req.session.get('example');
console.log(req.session.id);
req.reply(example);
}
});
in both cases the response headers are 200:
access-control-allow-origin... *
access-control-allow-cred... true
the kids show it on server are the same but i don't receive any response
any info will be really helpful! thanks!
I'm looking for a way to prevent yar from assigning a session cookie on specific routes. Particularly on routes that serve my static assets. Is there a way to disable it by passing in options to the plugin?
Is there a way to set "keepAlive" like with hapi-auth-cookie?
Just need to add attributes
. For full migration to v6.0 look at the hapi6 branch (not ready for integration as hapi v6.0 has not been published, but adding attributes
now is safe).
https://github.com/spumko/yar/blob/master/lib/index.js#L181
request.session is null there for one of my users. Guessing somehow I borked his session object but wondering if we should check for the existence of request.session before accessing it's properties?
I have catbox-redis set up as my server side cache. I'm not entirely sure what I'm doing incorrectly to cause a disconnect error whenever I write a large json object to a session key.
server.pack.register(
{
plugin: require('yar'),
options: {
cookieOptions: {
password: "its a password",
isSecure: false
},
cache: {
engine: require('catbox-redis'),
host: '127.0.0.1',
port: '6379'
}
}
}, function(err){
if(err){
console.log(err)
}
server.start();
And my request handler is something like this:
module.exports = function (request, reply) {
var user = request.session.get('user');
functionThatAppendsData(user);
request.session.set('user', user);
reply(user);
};
It's not exactly like this but it's the general effect and I didn't want to bog you down with the details of my application.
What do you think could be causing the disconnect?
within run the example.js the error occurred:
request.session.test = 1;
^
TypeError: Cannot set property 'test' of null
With debug, the session object is null.
When using memcache alongside yar, I get this error when a set operation occurs on memcache :
node: ../src/stream_wrap.cc:339: static v8::Handle<v8::Value>
node::StreamWrap::WriteStringImpl(const v8::Arguments&) [with node::encoding encoding = UTF8]:
Assertion `args.Holder()->InternalFieldCount() > 0' failed.
This never happen when manipulating memcache from catbox in route code. I believe there might be an issue with sockets & node domains (I saw that hapi was protecting its plugin calls properly using domains).
Any thoughts on this ? Because right now I'm really confused and I don't know at all how to get along with this.
flash messages gets not deleted after reading. they're deleted for the specific request, but the next time they are in the session again.
I've just tested the node.js (v 0.10.36), npm (2.4.1). Checking only for session handling here
package.json dependencies:
"dependencies": {
"hapi": "^8.1.0",
"yar": "^3.0.3"
}
app.js code
var Hapi = require('hapi');
var server = new Hapi.Server();
var options = {
cookieOptions: {
password: 'password',
isSecure: false
}
};
server.register(
{
register: require('yar'),
options: options
}, function (err) {
if (err) {
console.log('Error occured in loading', err);}
}
);
server.connection({ port: 3000 });
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
console.log("======= session ==============", request.session);
}
});
server.start(function () {
console.log('Options: ', options);
console.log('Server running at:', server.info.uri);
});
When this runs it prints session as null. Please let me know anything wrong with the code or anything missing? Looks like it doesn't initialize the session for request? No errors present either.
Instead of passing ttl or store, the new options take the hapi cache object used by plugin.cache() directly.
Hello to all,
So problem is next - we have several workers in cluster. 2 of them receive requests almost at the same time - each of them read session storage (MongoDB in our case). In parallel they are finishing their work and save all values of from session
request.session._store
to cache storage. And one of them override value of another, because both of them doesn't see changes of another and dump all data to storage. I'm wondering if exist some technics to avoid such behavior using yar ? Because from my point of view - we should implement in yar some atomic updates, but it should be implemented in catbox adapters too, which requires too much changes in core of Hapi.
The old MongoDB.Server(host, port, options) is only able to connect to a single mongod instance (if I am reading the docs right).
If you are using a replica set, which would be a good idea for production environments, then you need to connect to the entire replica set, not just the ephemeral current master in the set.
Perhaps it would make sense to migrate to the newer MongoClient class?
Using MongoClient.connect(connectionString, callback) would allow a user to just specify the connection string, and allow them to connect to any arbitrary configuration of MongoDB they are implementing.
Setting a cookie, then navigating away from the initial site causes the cookie to expire.
I've set up a repo to illustrate the issue:
https://github.com/Eruant/test-hapi-yar
It contains two servers that have links to each other. On each server a cookie is set, which increments on every visit. Refreshing the page shows that the cookie is working as expected. Then following the link to the second server and back results in the first cookie being removed and created again.
The cookie has been set to last for 7 days.
I am making a login page where i am handling session with Yar.
request.session.set('userid', { key: '1 });
Seems to set the value, but i cant access it in other handler. I am setting this value on the login page and when i redirected to home page i receive a null value in response to request.session.get('userid');
Please guide.
Thanks.
Sorry if this should be obvious, but is there a way to make the session persist (client-side)? Currently if the user closes their browser, the session is gone.
I can’t find anywhere that the Expires
option is added to the session cookie.
hapi v12 removes the request.session
placeholder. It will not break this module but you should officially decorate the request with the key to make sure other plugins can't if both are loaded. It might be best to call it something more unique like request.yar
so that other plugins like (hapi-auth-cookie) won't have a conflict (as they should stop using the request.auth.session
key).
I open the same route in different two browsers, but I got the sample request.yar.id
; is that normal?
I've got code in my server such as:
plugin.ext('onPreResponse', function (request, reply) {
if (request.response.variety === 'view') {
request.response.source.context = Hoek.applyToDefaults({
flash: request.session.flash()
}, request.response.source.context);
}
reply();
});
And then in a route POST /foo
, I'm calling:
request.session.flash('success', 'Item saved successfully');
reply.redirect('/');
I'd expect that if I reload '/', that the I wouldn't see the success
message again. I'd also expect that if I navigate to another page, I'd not have the flash
value still there. That is, I'd expect request.session.flash() to only return the values stored once, and then invalidate them.
However, this doesn't seem to be the case.
Right now, Passport uses a hacked version to simulate request.flash. A proper version should only take like 1-3 hours to implement when not under duress.
It would be very useful to be able to set an expiry on the keys stored, not just for the entire session.
Get them working.
It seems 2.0.0-rc1 of statehood doesn't exist on npm and that breaks the installation of yar.
Would be awesome if we could just change the dependency to 2.x.x as 2.0.0 has been released.
@OmniJeff Any reservations to a PR making the session duration configurable?
Re: https://twitter.com/hapijs/status/421216281866407937
I'm not encountering any errors, it's just not loading into redis.
This is being sent over:
var Catbox = require('catbox');
var client = new Catbox.Client({
engine: 'redis',
partition: 'dERP-session',
host: '127.0.0.1',
port: 6379,
password: ''
});
config = {
session: {
store: client.start(function () {
return new Catbox.Policy({ expiresIn: 14400 }, client, 'dERP');
}),
cookieOptions: {
password: 'FR9EtT]gA6&B~q4',
isSecure: false
}
}
var server = new Hapi.Server(config.server.port, config.server.options);
server.pack.allow({ ext: true }).require('yar', config.session, function (err) {
if (err) {
console.log(err)
throw err;
}
});
Hi,
It is security issue, which you might face. If one would like to .reset() session, here what happens:
request.session.reset = function () {
request.session.id = Uuid.v4(); // NEW ID IS GENERATED
request.session._store = {};
request.session._isModified = true;
cache.drop(request.session.id, function (err) { }); // NEW SESSION IS dropped from cache, while the initial session stays in cache, which has a high security risk
};
So, probably the last line with dropping from the cache should be the first one? (that way session is removed from cache, and than new ID assigned?)
I am setting a session variable in first request and in the next request for the same session, I want to get the variable value but when getting the value, the type of the object for the variable is changed.
E.g.
However, when i get the value of the variable, the type is set to Object and not of my custom type. Is there something i have to set? What am i missing?
With manual override and support for x-forwarded-proto
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.