Coder Social home page Coder Social logo

session's Introduction

koa-session

NPM version Node.js CI npm download

Simple session middleware for Koa. Defaults to cookie-based sessions and supports external stores.

Requires Node 8.0.0 or greater for async/await support

Installation

$ npm install koa-session

Notice

6.x changed the default cookie key from koa:sess to koa.sess to ensure set-cookie value valid with HTTP spec.see issue. If you want to be compatible with the previous version, you can manually set config.key to koa:sess.

Example

View counter example:

const session = require('koa-session');
const Koa = require('koa');
const app = new Koa();

app.keys = ['some secret hurr'];

const CONFIG = {
  key: 'koa.sess', /** (string) cookie key (default is koa.sess) */
  /** (number || 'session') maxAge in ms (default is 1 days) */
  /** 'session' will result in a cookie that expires when session/browser is closed */
  /** Warning: If a session cookie is stolen, this cookie will never expire */
  maxAge: 86400000,
  autoCommit: true, /** (boolean) automatically commit headers (default true) */
  overwrite: true, /** (boolean) can overwrite or not (default true) */
  httpOnly: true, /** (boolean) httpOnly or not (default true) */
  signed: true, /** (boolean) signed or not (default true) */
  rolling: false, /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. (default is false) */
  renew: false, /** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/
  secure: true, /** (boolean) secure cookie*/
  sameSite: null, /** (string) session cookie sameSite options (default null, don't set it) */
};

app.use(session(CONFIG, app));
// or if you prefer all default config, just use => app.use(session(app));

app.use(ctx => {
  // ignore favicon
  if (ctx.path === '/favicon.ico') return;

  let n = ctx.session.views || 0;
  ctx.session.views = ++n;
  ctx.body = n + ' views';
});

app.listen(3000);
console.log('listening on port 3000');

API

Options

The cookie name is controlled by the key option, which defaults to "koa.sess". All other options are passed to ctx.cookies.get() and ctx.cookies.set() allowing you to control security, domain, path, and signing among other settings.

Custom encode/decode Support

Use options.encode and options.decode to customize your own encode/decode methods.

Hooks

  • valid(): valid session value before use it
  • beforeSave(): hook before save session

External Session Stores

The session is stored in a cookie by default, but it has some disadvantages:

You can store the session content in external stores (Redis, MongoDB or other DBs) by passing options.store with three methods (these need to be async functions):

  • get(key, maxAge, { rolling, ctx }): get session object by key
  • set(key, sess, maxAge, { rolling, changed, ctx }): set session object for key, with a maxAge (in ms)
  • destroy(key, {ctx}): destroy session for key

Once you pass options.store, session storage is dependent on your external store -- you can't access the session if your external store is down. Use external session stores only if necessary, avoid using session as a cache, keep the session lean, and store it in a cookie if possible!

The way of generating external session id is controlled by the options.genid(ctx), which defaults to uuid.v4().

If you want to add prefix for all external session id, you can use options.prefix, it will not work if options.genid(ctx) present.

If your session store requires data or utilities from context, opts.ContextStore is also supported. ContextStore must be a class which claims three instance methods demonstrated above. new ContextStore(ctx) will be executed on every request.

Events

koa-session will emit event on app when session expired or invalid:

  • session:missed: can't get session value from external store.
  • session:invalid: session value is invalid.
  • session:expired: session value is expired.

Custom External Key

External key is used the cookie by default, but you can use options.externalKey to customize your own external key methods. options.externalKey with two methods:

  • get(ctx): get the external key
  • set(ctx, value): set the external key

Session#isNew

Returns true if the session is new.

if (this.session.isNew) {
  // user has not logged in
} else {
  // user has already logged in
}

Session#maxAge

Get cookie's maxAge.

Session#maxAge=

Set cookie's maxAge.

Session#externalKey

Get session external key, only exist when external session store present.

Session#save()

Save this session no matter whether it is populated.

Session#manuallyCommit()

Session headers are auto committed by default. Use this if autoCommit is set to false.

Destroying a session

To destroy a session simply set it to null:

this.session = null;

License

MIT

session's People

Contributors

adrianocola avatar dead-horse avatar dominicegginton avatar doug-wade avatar fengmk2 avatar galvez avatar isdongyu avatar jgrayauskie avatar jlarsson avatar jmitchell38488 avatar jonathanong avatar juliangruber avatar kpman avatar kroleg avatar lehni avatar limianwang avatar maples7 avatar mbehtemam avatar myyellowshoe avatar natesilva avatar ngorror avatar piggyman007 avatar popomore avatar runrioter avatar shaoshuai0102 avatar tj avatar vicanso avatar welll avatar xie-qianyue avatar zacanger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

session's Issues

Cannot set property 'maxAge' of undefined

After update to version "koa-session": "^3.1.0" ("koa": "~0.18.1")
Getting this error

TypeError: Cannot set property 'maxAge' of undefined
      at new Session (/Users/butuzgol/Playground/game/node_modules/koa-session/index.js:152:59)
      at Object.session (/Users/butuzgol/Playground/game/node_modules/koa-session/index.js:64:16)
      at Object.properties.(anonymous function).get (/Users/butuzgol/Playground/game/node_modules/koa-passport/lib/framework/request.js:99:21)
      at Function.initialize (/Users/butuzgol/Playground/game/node_modules/koa-passport/node_modules/passport/lib/middleware/initialize.js:50:12)
      at /Users/butuzgol/Playground/game/node_modules/co/index.js:135:8
      at Object.thunkToPromise (/Users/butuzgol/Playground/game/node_modules/co/index.js:134:10)
      at Object.toPromise (/Users/butuzgol/Playground/game/node_modules/co/index.js:118:55)
      at next (/Users/butuzgol/Playground/game/node_modules/co/index.js:98:29)
      at onFulfilled (/Users/butuzgol/Playground/game/node_modules/co/index.js:68:7)
      at /Users/butuzgol/Playground/game/node_modules/co/index.js:53:5

On "koa-session": "^2.0.0" works fine

The session is wrong

when I test this code:
var session = require('koa-session');
var koa = require('koa');
var app = koa();

app.keys = ['some secret hurr'];
app.use(session(app));

app.use(function *(){
var n = this.session.views || 0;
this.session.views = ++n;
this.body = n + ' views';
})

app.listen(3000);

console.log('listening on port 3000');

The browser give the first result: 3 views, 5 views,7....
why?

allow keys with `_`

just a reminder. going to include this in the next version with cookies v1

only set sessions if not empty

This module provides "guest" sessions, meaning any visitor will have a session, authenticated or not. If a session is new a Set-Cookie will be produced regardless of populating the session.

and by not empty i mean there's more attributes than just .sid. you don't want your static middleware concurrently creating a bunch of cookies.

cannot set maxAge for special client

for now. session options is global object.
if a user check 'remember me' checkbox then login.
i cannot set special maxAge for him. because session will overwrite it in future.

about the assert of app.use()

when I run the example.js, just get

AssertionError: app.use() requires a generator function
    at Application.app.use (/....../koa/lib/application.js:83:3)
    at Object.<anonymous> (/....../example.js:10:5)

I add the console.log before assert

app.use = function(fn){
  console.log(fn.constructor)
  console.log(fn().constructor)
  assert('GeneratorFunction' == fn.constructor.name, 'app.use() requires a generator function');
  debug('use %s', fn.name || '-');
  this.middleware.push(fn);
  return this;
};

and the log is:

[Function: GeneratorFunction]
[Function: GeneratorFunctionPrototype]
[Function: Function]
[Function: GeneratorFunction]

the most strange is: everything is ok yesterday!

koa session does not work when used in a middleware app

I am using the vhost middleware with koa-session. Since koa-session 2.0.0 is was possible to use it in a subapp. Since 3.0.0 this does not work anymore. Example:

var session = require('./');
var koa = require('koa');
var compose = require('koa-compose');
var app = koa();

app.keys = ['some secret hurr'];

app.use(session(app));

app.use(function* (next){
  if ('/favicon.ico' == this.path) return;
  var n = this.session.views || 0;
  this.session.views = ++n;
  this.body = n + ' views';
});

var server = koa();
server.use(compose(app.middleware));
server.listen(3000);

console.log('listening on port 3000');

set option httpOnly dosen't work

I was using koa-session.
While I set httpOnly prop like this:

var nickName = encodeURIComponent(userData.data.nick),
        empId = encodeURIComponent(userData.data.empid);
    var cookiesOpt = {
        maxAge : 1296000000,
        path : '/',
        httpOnly: false
    };
    this.cookies.set('nick', nickName, cookiesOpt);
    this.cookies.set('empId', empId, cookiesOpt);

I want to get all cookies through document.cookie. but the cookies still have http flag.
Did I miss something?

the default setting session is cookie?

The default setting put session in client cookie, is it safe? As I know cookie work in client and session just put an sessionId in client take session value in server side . koa-session without store put session value in cookie even if it is encoded but I think all from client is not worthy of trust.

Adding an additional session

I would like to introduce a secure session in our app changing the existing and behaviour of this.session. So, for example I might add this.secure_session and provide my own encode and decode methods.

Could this be as simple as adding a context_name configuration?

const session = require('koa-session')
const cryptoSession = require('koa-crypto-session')

app.use(session({context_name: 'session'}, app));
app.use(cryptoSession({context_name: 'secure_session'}, app));

// this.session
// this.secure_session

I found two references to 'session' .. __defineGetter__ and __defineSetter__

Why modify app

Hey guys,
I'm starting a new project soon and currently deciding which libraries I will be using.
Now I peaked into the source of this repo, and I wondered, why you guys are needing the app for initialization? Other session middlewares are just modifying the ctx object, not the whole app?

Change project description to make it clear external session stores can be used

We were using a different session module. I never looked at koa-session because the description sounds like it only supports cookies (we use Redis). Turns out, it’s easy to plug Redis into koa-session.

It would be helpful to edit the project description on Github and package.json so dummies like me will give this a try. This is the most-downloaded Koa session middleware and should be the go-to module for all session needs.

Default cookie name doesn't satisfy RFC6265

The default cookie name koa:sess contains :, which is not a valid token character in accordance with RFC6265 and RFC2616. Although most web browsers and servers allow this, it causes problems in some more strict environment such as spray.

Would you consider remaining it? If so, should we take backward compatibility into account?

csrf

you think we should bake it in? i think it's easier and not too complicated to bake it in since in this case, the "secret" can be retrieved synchronously and lazily, but in db stores, the "secret" has to be retrieved asynchronously and/or the session already has to be retrieved.

should we auto update expired value every time user connect to server?

currently expire value is never change until it is expired.

e.g., if maxAge is 3 minutes

if user always interact with server, that user can play within only 3 minutes and need to re-login.

is it better if koa-session auto update exired value and then user does not need to re-login for every 3 minutes?

Session destroying its self after adding an object to it

I have opened a stackoverflow question about it:

http://stackoverflow.com/questions/35050999/koa-session-getting-reset-after-appending-object-to-it

But I'll copy pasta it here anyways

I have a controller which looks up a character, and then does some stuff with it, the controller looks like:

    router.post('/profile/characters', async ctx => {
        try {
            ctx.type = 'json';
            let req = ctx.request;
            if (!('charname' in req.body) || !('charserver' in req.body)) {
                return res.json({
                    'success': false,
                    error: 'You are missing either the character name, or server'
                });
            }

            let foundChar = await new Promise((res, rej) => {
                bnet.wow.character.aggregate({
                    origin: 'us',
                    realm: req.body.charserver,
                    name: req.body.charname,
                    fields: ['items', 'talents']
                }, (err, charData) => {
                    if (err) {
                        console.log(err);
                        return rej(err);
                    }
                    return res(charData);
                });
            });


            if ('status' in foundChar) {
                if (foundChar.status === 'nok') {
                    return ctx.body = {
                        'success': false,
                        error: 'There was an error looking up your character, please ensure its a US character, and has been logged into recently'
                    };
                }
            }

            foundChar.items.level = foundChar.level;
            foundChar.items.class = foundChar.class;
            foundChar.items.thumbnail = foundChar.thumbnail;
            foundChar.items.name = foundChar.name;

            let {
                items, talents
            } = foundChar;

            let specF = talents.find(x => x.selected) || {};
            let charData = {
                items, specF
            };

            if ('legs' in items || 'hands' in items || 'shoulder' in items) {
                return ctx.body = {
                    success: false,
                    error: 'To verify it is your own character, please remove your (Shoulders, Hands, and Pants) from your character and try again.'
                };
            }

            ctx.session.foundChar = foundChar; // This line here
            console.log(ctx.session);
            ctx.body = {
                success: true,
                charData
            };

        } catch (err) {
            console.log(err);
            ctx.status = err.status || 500;
            ctx.body = {
                message: err.message
            };
        }
    });

When it processes ctx.session.foundChar = foundChar it seems to reset my session for some reason, and logging the session shows {} instead of

    { 
       authenticated: true,
       userid: 1
       ...
    }

But if I change ctx.session.foundChar = "Hello"; < Works just fine.

I don't know if there is a data limit or something to the session or what as this wasn't an issue with express-session but I'm trying to convert it all over to Koa, anyways not sure why my session is getting reset.

Example of what foundChar looks like

    { userid: 1,
      username: 'Blah',
      authenticated: true,
      userLevel: 5,
      hasMainCharacter: true,
      foundChar:
       { lastModified: 1453702285000,
         name: 'Blah',
         realm: 'Mal\'Ganis',
         battlegroup: 'Vindication',
         class: 4,
         race: 5,
         gender: 0,
         level: 100,
         achievementPoints: 6335,
         thumbnail: 'internal-record-3684/9/119507209-avatar.jpg',
         calcClass: 'c',
         faction: 1,
         items:
          { averageItemLevel: 714,
            averageItemLevelEquipped: 573,
            head: [Object],
            neck: [Object],
            back: [Object],
            chest: [Object],
            wrist: [Object],
            waist: [Object],
            feet: [Object],
            finger1: [Object],
            finger2: [Object],
            trinket1: [Object],
            trinket2: [Object],
            mainHand: [Object],
            offHand: [Object],
            level: 100,
            class: 4,
            thumbnail: 'internal-record-3684/9/119507209-avatar.jpg',
            name: 'Blah' },
         talents: [ [Object], [Object] ],
         totalHonorableKills: 258 } }

So this logs properly, but then after refreshing the page im no longer authenticated and ctx.session is {}

observable session

automatically save the session when it changes via Object.observe(). maybe opt-in. would especially be useful if we make session a context property instead of middleware. in this case, we should set the overwrite option to cookies as true.

we should also make sure to throw if the user changes the session after .headerSent.

Pluggable storage layers

Hey, I needed to be able to use Mongo for the session back-end so I went ahead and wrote my own session middleware for this. As it turns out I ended up using most of koa-session and what I have works almost exactly the same (and even uses the same tests):

https://github.com/hiddentao/koa-session-store

It defaults to storing in the cookie but you can supply a 'layer object' instead. I've written a MongoDB layer - koa-session-mongo - which is based on the connect-mongo module.

If you like it then I'd be more than happy to fork koa-session and raise a pull request with all the changes. At the very least it would make the naming better:

  • koa-session - the core module
  • koa-session-* - a specific storage layer

session = null, session = {}

session = null should clear the session. session = {} should replace the session with this object and add an .id if not supplied already.

typo in Session.prototype.save method

try {
    json = opts.encode(json);
    debug('save %s', json);
  } catch (e) {
    debug('encode %j error: %s', json, err);
    json = '';
  }

e || err:
catch (e) .... -> debug('encode %j error: %s', json, err);

Session signature is same

The session signature is same for all requests and also the session object is visible to the client as koa:sess={ "json" : "stringified" } . I am coming from express background and there the connect.sid is random for every Set-Cookie and value of req.session is not exposed to client . Also this does not contain store implementation right ? . Please direct me on this .

error when set session

Error: .keys required for signed cookies

var session = require('koa-session');
router.get('/getScore', koaBody, session(app),function *(){
var n = this.session.views || 0;
this.session.views = ++n;
this.body = n + ' views';
})
app.use(convert(session( app)));

Help me please! thk

Module deprecated?

In favor of generic-session?

Or is it looking for new maintainers? We had some problem moving from v3.0 to v3.1; it seems the backwards compatible change isn't so compatible.

simov/grant#9

remove session.sid

i'm not sure it's necessary. i don't think connect uses an "id" for its cookie session either. only use is for CSRF, but i feel like people are going to be like "i want the uid to be 24 characters long instead of 15" or something.

sid is only necessary for db stores IMO

session is worked between two different server with the same ip and host

I am using this middleware for my koa project . And during my coding ,i found this session hasn't been destoryed after i closed my server. As i could access the http request in the same web page which i didn't close before.

My config is like :
var CONFIG = {
key: 'koa:sess', /** (string) cookie key (default is koa:sess) /
maxAge: 0, /
* (number) maxAge in ms (default is 1 days) /
overwrite: true, /
* (boolean) can overwrite or not (default true) /
httpOnly: true, /
* (boolean) httpOnly or not (default true) /
signed: true, /
* (boolean) signed or not (default true) */
};

And i focus that this module is based on cookie which means it will still be alive even when the server has been closed. Am i right?

parse the cookie lazily

was gonna write this but as a context helper that parses the session as a getter. i.e.

context.__defineGetter__('session', function(){
  return this._session || (this._session = new Session(this))
})

because i don't like middleware :P

option to only save when `isNew` if populated

ie the user would have to set something. i think this is pretty opinionated and should be an option. or do you think it should be default? i guess the only time you wouldn't want this is if you're doing something with the .sids without touching the cookie.

session regeneration

some method definition is required for reset/regeneration of session. if any please inform.

Cannot set cookie expires to be 'Session'.

In Version 4.0.1(we haven't upgraded to node > 7 yet), the maxAge property has to be a number and by default will set the expires of the browser cookie to now + 24 hours.

screen shot 2017-05-24 at 2 43 58 pm

For more secure browser sessions, it would be great to have the cookie expire when the browser is closed. This is not possible currently.

Would like to be able to set expires too:
screen shot 2017-05-24 at 2 44 43 pm

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.