Curveball Session Middleware
This package adds support for sessions to the Curveball1 framework.Features:
- It's lazy. It will only start a session if there is something in the store.
- It will also automatically wipe the session data if session data was emptied.
- It provides features for generating and validating CSRF tokens.
Installation
npm install @curveball/session
Upgrading from versions 0.5 and below
If you are upgrading from a 0.5.x release or earlier, this package introduces a BC break since 0.6.In 0.5 session data was available in
ctx.state.session
and
ctx.state.sessionId
, but this has been moved to ctx.session
and
ctx.sessionId
.Getting started
Adding the middleware
import session from '@curveball/session';
app.use(session({
store: 'memory',
});
This will add the in-memory session store to curveball. This store is mostly meant for testing.
Here is another example with more options:
import session from '@curveball/session';
app.use(session({
store: 'memory',
cookieName: 'MY_SESSION',
expiry: 7200,
cookieOptions: {
secure: true,
path: '/',
sameSite: true,
},
});
cookieName
- Updates the name of the HTTP Cookie. It'sCB
by default.expiry
- The number of seconds of inactivity before the session disappears.
cookieOptions
- If set, override cookie options from the default. The list
Using the session store
In your own controllers and middlewares, you can set and update session data via thectx.session
property.app.use( ctx => {
// Running this will create the session
ctx.session = { userId: 5 };
ctx.response.body = 'Hello world';
});
Deleting a session
To delete an open session, just clear the session data:app.use( ctx => {
// Running this will create the session
ctx.session = null;
});
Re-generate a session id.
If you clear the session id, but there is still data, the middleware will remove the old session and automatically create a new session id:app.use( ctx => {
// This will kill the old session and start a new one with the same data.
ctx.sessionId = null;
});
CSRF token support
To obtain a CSRF token for forms, the middleware provides agetCsrf()
function:app.use( async ctx => {
// Obtain a CSRF token for HTML forms:
const csrfToken = await ctx.getCsrf();
});
It's recommended to embed this token in HTML forms as such:
<input type="hidden" name="csrf-token" value="....token goes here" />
Then on
POST
requests, you can easily validate the token with the validateCsrf
function. If the token was incorrect, this will automatically result in a 403
error:app.use(route.post('/form-submit', ctx => {
// Throws error if csrf-token was not supplied or incorrect
ctx.validateCsrf();
}));
API
It's desirable to create your own stores for product usage. Eventually this project will probably add a few more default stores.Until then, you must implement the following interface:
interface SessionStore {
set(id: string, values: SessionValues, expire: number): Promise<void>;
get(id: string): Promise<SessionValues>,
delete(id: string): Promise<void>,
newSessionId(): Promise<string>,
}
SessionValues
is simply a key->value object. expire
is expressed as a unix
timestamp.