Keystone Nextpreview

Session API

The session property of the system configuration object allows you to configure session management of your Keystone system. It has a TypeScript type of () => SessionStrategy<any>. In general you will use functions from the @keystone-next/keystone/session package, rather than writing this function yourself.

import { config } from '@keystone-next/keystone/schema';
import { statelessSessions, withItemData } from '@keystone-next/keystone/session';
export default config({
session: withItemData(
secret: 'ABCDEFGH1234567887654321HGFEDCBA',
ironOptions: { /* ... */ },
maxAge: 60 * 60 * 24,
secure: true,
path: '/',
domain: 'localhost',
{ User: 'name isAdmin' }
/* ... */

Stateless vs stored sessions

Keystone supports both stateless and stored sessions. In a stateless session all session data is stored in a cookie. In a stored session a session ID is stored in the cookie, and this ID is used to save and load data from a data store on the server. All cookies are encrypted with @hapi/iron.

Both statelessSessions() and storedSessions() accept a common set of arguments which control the behaviour of the cookies. storedSessions() accepts an additional store argument, which is an object capable of loading and storing session data.

import { config } from '@keystone-next/keystone/schema';
import { statelessSessions, storedSessions } from '@keystone-next/keystone/session';
export default config({
// Stateless
session: statelessSessions({ /* ... */ }),
// Stored
session: storedSessions({ store: { /* ... */ }, /* ... */ }),
/* ... */


  • secret (required): The secret used by @hapi/iron for encrypting the cookie data. Must be at least 32 characters long.
  • ironOptions: Additional options to be passed to Iron.seal() and Iron.unseal() when encrypting and decrypting the cookies. See the @hapi/iron docs for details.
  • maxAge (default: 60 * 60 * 8 (8 hours)): The number of seconds until the cookie expires.
  • secure (default: process.env.NODE_ENV === 'production): If true, the cookie is only sent to the server when a request is made with the https: scheme (except on localhost), and therefore is more resistent to man-in-the-middle attacks. Note: Do not assume that secure prevents all access to sensitive information in cookies (session keys, login details, etc.). Cookies with this attribute can still be read/modified with access to the client's hard disk, or from JavaScript if the HttpOnly cookie attribute is not set. Note: Insecure sites (http:) can't set cookies with the secure attribute (since Chrome 52 and Firefox 52). For Firefox, the https: requirements are ignored when the secure attribute is set by localhost (since Firefox 75).
  • path (default: '/'): A path that must exist in the requested URL, or the browser won't send the cookie header. The forward slash (/) character is interpreted as a directory separator, and subdirectories will be matched as well: for path: '/docs', /docs, /docs/Web/, and /docs/Web/HTTP will all match.
  • domain (default: current document URL): Host to which the cookie will be sent. See here for more details on the domain cookie attribute.. Note: Only one domain is allowed. If a domain is specified then subdomains are always included.

Session stores

When using storedSessions you need to pass in a session store as the store option. This store option must be either a SessionStore object, or a function ({ maxAge }) => { ... } which returns a SessionStore object.

A SessionStore object has the following interface:

const store = {
connect: () => { /* ... */ },
disconnect: () => { /* ... */ },
set: (sessionId, data) => { /* ... */ },
get: sessionId => {
/* ... */
return data;
delete: sessionId => { /* ... */ },


  • connect: Connect to the session store.
  • disconnect: Disconnect from the session store.
  • set: Set a value data for the key sessionId.
  • get: Get the data value associated with sessionId.
  • delete: Delete the entry associated with sessionId from the session store.

Keystone provides a Redis based session store in the package @keystone-next/session-store-redis.

import redis from `redis`;
import { redisSessionStore } from '@keystone-next/session-store-redis`;
import { config } from '@keystone-next/keystone/schema';
import { storedSessions } from '@keystone-next/keystone/session';
export default config({
session: storedSessions({
store: redisSessionStore({ client: redis.createClient() }),
/* ... */,
/* ... */

Session context

If you configure your Keystone session with session management then the KeystoneContext type will include three session related properties.

  • session: An object representing the session data. The value will depend on the value passed into context.startSession().
  • startSession: A function data => {...} which will start a new session using the provided data value.
  • endSession: A function () => {...} which will end the current session.

The startSession and endSession functions will be used by authentication mutations to start and end authenticated sessions. These mutations will set the value of session to include the values { listKey, itemId }.

Authenticated item data

The authentication mutations provide values { listKey, itemId } for the context.session object. You will often need to know more than just the itemId of the authenticated user, such as when performing access-control or using hooks.

Keystone provides the wrapper function withItemData(), which will inject an additional value data onto the context.session object. This data value will be populated based on the value of listKey and itemId from the wrapped session strategy, and the configuration options passed to withItemData().

withItemData() accepts two arguments. The first is the session strategy to be wrapped, such as statelessSessions() or storedSessions(). The second argument is an oject of the form { [listKey]: query }. When the session data is created, the wrapper function will look up the item in the list listKey, performing a GraphQL query filtering on itemId and returning the fields in query. The returned item will be available as

import { config } from '@keystone-next/keystone/schema';
import { statelessSessions, withItemData } from '@keystone-next/keystone/session';
export default config({
session: withItemData(
statelessSessions({ /* ... */ }),
{ User: 'name isAdmin' }
/* ... */

On this page

  • Session API
  • Stateless vs stored sessions
  • Session stores
  • Session context
  • Authenticated item data