Installation:

npm: npm install @hapi/yar

yarn: yarn add @hapi/yar

Introduction

yar add session support to hapi - a persistent state across multiple browser requests using an iron encrypted cookie and server-side storage. yar tries to fit session data into a session cookie based on a configured maximum size. If the content is too big to fit, it uses server storage via the hapi plugin cache interface.

Differences from @hapi/cookie

The @hapi/cookie plugin provides similar facilities to yar. The approach of the two projects does differ in some regards, though.

  1. yar is focused on session support, and does not require that a user be logged in to have a session. @hapi/cookie only provides session storage for logged in users. If you need session handling for non-authenticated users, use yar.
  2. yar is capable of handling larger data sizes without any additional setup. If your session data gets larger than cookies can handle yar will push the data out to the server cache for you. By default this is memory storage, but can be any catbox supported cache storage, including mongo, redis, local disk, and more. @hapi/cookie can support larger session size as well, but requires you to handle connecting the cookie based session with your external data storage.

Example

For example, the first handler sets a session key and the second gets it:

let handler1 = (request, reply) => {

    request.yar.set('example', { key: 'value' });

    return null;
};

let handler2 = (request, reply) => {

    const example = request.yar.get('example');
    return example.key;     // Will send back 'value'
};

The plugin requires a password for encryption that must be at least 32 characters long:

let options = {
    storeBlank: false,
    cookieOptions: {
        password: 'the-password-must-be-at-least-32-characters-long',
        isSecure: true
    }
};
/*
Please note that there are other default cookie options that can impact your security.
Please look at the description of the cookie options below to make sure this is doing
what you expect.
*/

const server = new Hapi.Server();

try {
  await server.register({
      plugin: require('@hapi/yar'),
      options: options
  });
} catch(err) {
    console.error(err);
}

await server.start();

Password considerations

Keep in mind some things in regard to your password:

  1. It should never be committed to the repository or hard coded in your code. Instead pass the password via environment variables or some other server configuration management option.
  2. In some situations it is possible that your password could be attacked remotely. So choose a password that is randomly generated. Use a random password generator to create something rather than creating your own. Make sure it is long and includes special characters.
  3. Consider rotating your cookie session password on a regular basis.

Cookie Options

You can read about more cookie options in the Api.

isSecure

Set isSecure (default true) to false if you are using standard http. Take care to do this in development mode only though. You don't want to use cookies sent over insecure channels for session management. One way to take care of this is to use the NODE_ENV environment variable like this:

let options = {
    cookieOptions: {
        isSecure: process.env.NODE_ENV !== 'development',
        ...
    }
};

ignoreErrors

ignoreErrors (default true) tells hapi that it should not respond with a HTTP 400 error if the session cookie cannot decrypt. This could happen if the cookie is changed on the client, or more likely, if you change the cookie password in your settings. If you want to make this condition send an error like it did in prior versions, change this to false, but be aware that if you change your cookie password you will cause 400 errors to be returned to end users. In that case you should probably change this back to true for a short time to allow session cookies to get reset for the best user experience.

You may turn this off, false, and try to use the hapi route state config option of failAction to instead get an event whenever a bad session cookie is encountered. This can allow more sophisticated handling strategies or even allow for mitigation of brute force attacks on your cookie password. See server.state documentation for more details.

clearInvalid

clearInvalid (default true) tells hapi that if a session cookie is invalid for any reason, to clear it from the browser. This prevents hapi from having to reprocess the bad cookie on future requests. In general you'll probably want this on, but if you'd prefer that session cookies be dealt with in some other way you may set this to false.

Options

  • name - determines the name of the cookie used to store session information. Defaults to session.
  • maxCookieSize - maximum cookie size before using server-side storage. Defaults to 1K. Set to zero to always use server-side storage.
  • storeBlank - determines whether to store empty session before they've been modified. Defaults to true.
  • errorOnCacheNotReady - will cause yar to throw an exception if trying to persist to cache when the cache is unavailable. Setting this to false will allow applications using yar to run uninterrupted if the cache is not ready (however sessions will not be saving). Defaults to true.
  • cache - hapi cache options which includes (among other options):
    • expiresIn - server-side storage expiration (defaults to 1 day).
  • cookieOptions - the configuration for cookie-specific features:
    • password - (Required) used to encrypt and sign the cookie data.
    • path - determines the cookie path. Defaults to '/'.
    • isSameSite - enables the same-site cookie parameter. Default to 'Lax'. Can be 'Strict'|'Lax'|false.
    • isSecure - determines whether or not to transfer using TLS/SSL. Defaults to true.
    • isHttpOnly - determines whether or not to set HttpOnly option in cookie. Defaults to false.
    • ttl - sets the time for the cookie to live in the browser, in milliseconds. Defaults to null (session time-life - cookies are deleted when the browser is closed).
  • customSessionIDGenerator - an optional function to create custom session IDs. Must retun a string and have the signature function (request) where:
    • request - (optional) is the original request received from the client.

Route Options

You can also add these options on a route per route basis at config.plugins.yar: - skip - a boolean value which, if true, means no session with be attached to the request (defaults to false).

Methods

yar adds the yar property to every request object and initializes the yar.id on the first request from each browser. The request.yar interface provides the following methods:

  • reset() - clears the session and assigns a new session id.
  • set(key, value) - assigns a value (string, object, etc) to a given key which will persist across requests. Returns the value.
  • set(keysObject) - assigns values to multiple keys using each 'keysObject' top-level property. Returns the keysObject.
  • get(key, clear) - retrieve value using a key. If 'clear' is 'true', key is cleared on return.
  • clear(key) - clears key.
  • touch() - Manually notify the session of changes (when using get() and changing the content of the returned reference directly without calling set()).
  • flash(type, message, isOverride) - stores volatile data - data that should be deleted once read. When given no arguments, it will return all of the flash messages and delete the originals. When given only a type, it will return all of the flash messages of that type and delete the originals. When given a type and a message, it will set or append that message to the given type. 'isOverride' used to indicate that the message provided should replace any existing value instead of being appended to it (defaults to false).
  • lazy(enabled) - if set to 'true', enables lazy mode. In lazy mode, request.yar can be modified directly (e.g. setting request.yar.myKey to an object value), and those keys will be stored and loaded back. Lazy mode isn't as fast as the normal get/set because it has to store the session state on every responses regardless of any changes being made.

yar adds the yar property to the server instance. The server.yar interface provides the following methods:

  • revoke(id) - revokes the specified session.

Changelog

#134
Update dep
#131
Change module namespace
#127
chore: update dependencies
#126
Add possibility to revoke specific session on the server side
#125
Minor: Deprecated use of uuid
#123
Delete a specific user's session
#124
Yar doesn't handle the session cookie multiple times correctly.
#122
Do not cast all falsy values to null
#121
Falsy values are converted to null
#110
Fix `main` in package.json
#90
add a route level config option to skip yar processing
6.0.0
breaking changes
#89
update yar to use request.yar instead of request.session
#88
Decorate request with session key
#83
Option to skip exception on cache error
#75
Allow specification of whether to store blank sessions
4.0.0
breaking changes
#80
ignore invalid cookies so we don't get 400 errors on servers, which i…
#65
"Invalid cookie value" after password change, but OK after refresh!
#79
Tests are failing
3.0.0
breaking changes
#61
Can't install yar from npm
#57
hapi 8.0. Closes #56
#56
hapi 8.0 API
#52
properly drop session during session.reset
#46
Hapi6
#45
Update examples, examples/package.json to use Hapi 6.x
#44
Updated readme to match hapi 6.x API
#43
Update tests / package.json to use Hapi 6.x
#41
errorhandling after cookie password changes
#32
Upgrade to Hapi 4.x
2.0.0
breaking changes
#29
Replace ttl and store with cache options
#28
Update to hapi 3.x
clipboard