Session Management

Learn how Wristband SDKs manage encrypted cookie-based sessions.

Your application keeps users logged in after the login flow completes by storing their session. Most backend server auth SDKs include session management that stores the session in an encrypted cookie in the user's browser, so no database or session store is required. Some SDKs build on their framework's own session system instead, and some let your application plug in its own session storage.

Since your auth endpoints rely on the session to store the user's tokens and data, configure session management before implementing the SDK's login, callback, and logout functions.

Setting Up Session Management

Session management is configured once when your application starts. The SDK then attaches a session to every incoming request, which your auth endpoints and route handlers use to read, update, save, and destroy session data.

For example, using the Express Auth SDK:

// src/wristband.ts
import { createWristbandSession } from '@wristband/express-auth/session';
 
const sessionOptions = {
  secrets: 'replace-me-with-a-secret-of-at-least-32-characters',
  maxAge: 3600, // 1 hour in seconds
  secure: process.env.NODE_ENV === 'production',
};
 
export function wristbandSession() {
  return createWristbandSession(sessionOptions);
}
// src/app.ts
import express from 'express';
import { wristbandSession } from './wristband';
 
const app = express();
 
// Attaches the session to req.session on every request.
app.use(wristbandSession());

Required Configuration

The only required value is secrets, the secret used to encrypt and decrypt the session cookie. It must be at least 32 characters, and should be a cryptographically random value kept out of source control. All other values are optional and have defaults.

SDKs built on a framework's session system are configured through that framework's settings instead.

See Session Configuration below for every available value.

How Sessions Work

The rest of this page describes SDKs that store sessions in an encrypted cookie. On each request, the SDK reads the session cookie and decrypts it with your session secret, giving your application access to the session data. When your application saves the session, the SDK encrypts the session data and writes it back to the session cookie on the response.

The SDK encrypts and authenticates session data, so the browser can't read or modify it. Any change to the cookie causes decryption to fail. The session cookie is also HttpOnly by default, so JavaScript running in the browser can't access it.

If the session cookie is missing, has expired, or can't be decrypted, the SDK doesn't throw an error. It starts the request with an empty session instead, which your application treats as unauthenticated.

Session Expiration

The maxAge setting controls how long a session lasts, in seconds. The default is 3600 (1 hour). The browser deletes the session cookie once maxAge has passed.

Some SDKs also store the time of encryption inside the encrypted cookie, and treat the session as expired once maxAge has passed since then, even if the browser still sends the cookie (e.g. Express). This check allows 60 seconds of tolerance for clock differences between servers.

Rolling Sessions

Every time the session is saved, the SDK resets its expiration to the current time plus maxAge. As long as the user stays active and the session keeps getting saved, they stay logged in. A session only expires after maxAge passes with no save. SDKs built on a framework's session system follow that framework's rules for extending expiration instead (e.g. ASP.NET Core sliding expiration).

For example, with a maxAge of one hour:

  1. A session created at 1:00 PM expires at 2:00 PM.
  2. The session is saved again during a request at 1:30 PM.
  3. The session now expires at 2:30 PM.

In SDKs that include auth middleware, the middleware saves the session on every authenticated request, so protected routes keep the session rolling automatically.

See Protecting Routes and APIs for more on the auth middleware.

Session Data

A session starts empty. Before login, every session field is undefined, and the session only gets data when your application creates it from the callback or sets fields on it directly.

Session Fields

Once your Callback Endpoint initializes the session after a successful login, the session contains the following fields. The SDK and your application rely on these fields for as long as the session lasts.

FieldTypeDescription
isAuthenticatedbooleanAlways set to true.
accessTokenstringThe access token from the callback data.
expiresAtnumberThe access token's expiration time, in milliseconds since the Unix epoch, with the tokenExpirationBuffer already subtracted.
userIdstringThe ID of the user (from userinfo.userId).
tenantIdstringThe ID of the user's tenant (from userinfo.tenantId).
tenantNamestringThe name of the user's tenant.
identityProviderNamestringThe name of the identity provider the user logged in with (from userinfo.identityProviderName).
refreshTokenstringThe refresh token. Only stored if the callback data includes one.
tenantCustomDomainstringThe tenant custom domain used during login. Only stored if the callback data includes one.

See Initializing Session Data below for how these fields are populated.

Custom Fields

The fromCallback() function also accepts an optional second argument with custom fields to store alongside the fields above. The custom fields must be JSON-serializable, or the function throws an error. For example, using the Express Auth SDK:

req.session.fromCallback(callbackData, {
  preferences: { theme: 'dark' },
  lastLogin: Date.now(),
});
await req.session.save();

Session Size

Browsers limit cookies to 4KB, and after encryption overhead, roughly 3KB is left for session data. Some SDKs throw an error when saving a session that would exceed the limit (e.g. Express and FastAPI).

To stay under the limit, store only essential data in the session, such as IDs, tokens, and minimal user information. For larger data, store it in your database and keep only a reference ID in the session. For example:

// Store a reference in the session.
req.session.cartId = 'cart_abc123';
 
// Fetch the full data from your database when needed.
const cart = await db.getCart(req.session.cartId);

Working With Sessions

During a request, your application reads and updates session data. Changes to the session are kept in memory while your application handles a request. They only reach the browser once the session cookie is written to the response, which happens when the session is saved or destroyed. How that write happens depends on the SDK:

  • Explicit save and destroy: Your application calls save() or destroy(), and the SDK writes the session cookie to the response the framework sends (e.g. Express).
  • Automatic on response: The SDK or framework detects session changes and writes the session cookie when the response is sent, so your application doesn't save the session itself (e.g. ASP.NET and Django).
  • Onto a returned response: Your application calls saveToResponse() or destroyToResponse() with the response it returns, and the SDK adds the session cookie to that response (e.g. the Next.js App Router).
🚧

Responses Must Not Be Cached

Responses that save or destroy the session carry one user's session cookie, so a browser or shared cache must never store them or serve them to another user. Some SDKs set the Cache-Control: no-store and Pragma: no-cache headers on these responses automatically (e.g. Express).

Initializing Session Data

After a successful login, your Callback Endpoint populates the session by passing the callback data to the session's fromCallback() function, which stores the fields listed in Session Fields above.

For example, using the Express Auth SDK:

app.get('/auth/callback', async (req, res) => {
  const callbackResult = await wristbandAuth.callback(req, res);
  // ...
  req.session.fromCallback(callbackResult.callbackData);
  // ...
});

Reading and Updating Session Data

Your application can read and set session fields directly as properties of the session. Most SDKs also provide getter and setter functions for the same operations, such as get(), set(), and delete(), and some only support access through functions (e.g. ASP.NET). Changes are kept in memory until the session is saved. All values stored in the session must be JSON-serializable.

For example, using the Express Auth SDK:

app.post('/api/settings', async (req, res) => {
  req.session.theme = 'dark';
  await req.session.save();
 
  res.status(200).json({
    userId: req.session.userId,
    theme: req.session.theme
  });
});

Saving Sessions

Saving encrypts the current session data, writes it to the session cookie, and resets the session's expiration. Your Callback Endpoint creates the first session after login, and your application saves the session again whenever it changes session data. In SDKs that include auth middleware, the middleware also saves the session on every authenticated request to keep it rolling so that active sessions don't expire.

For example, using the Express Auth SDK:

app.get('/auth/callback', async (req, res) => {
  // ...
  await req.session.save();
  // ...
});

See the Creating the Session section of Callback for more details.

Destroying Sessions

Destroying clears the session data and deletes the session cookie, along with the CSRF cookie when CSRF protection is on. In some SDKs, a destroyed session can't be modified or saved again (e.g. Express). Your Logout Endpoint should destroy the session when a user logs out. In most SDKs, it's also up to your application to destroy the session anywhere else it needs to end a user's session, such as after a token refresh fails.

For example, using the Express Auth SDK:

app.get('/auth/logout', async (req, res) => {
  // ...
  req.session.destroy();
  // ...
});

See the Destroying the Session section of Logout for more details.

Session and Token Endpoint Responses

Most SDKs provide two helper functions that build responses in the format Wristband frontend SDKs expect:

  • getSessionResponse(): Builds the Session Endpoint response from the session's userId and tenantId, plus any optional metadata your application passes in. The metadata values must be JSON-serializable.
  • getTokenResponse(): Builds the Token Endpoint response from the session's accessToken and expiresAt.

For example, the Session Endpoint response:

{
  "tenantId": "tenant_abc123",
  "userId": "user_xyz789",
  "metadata": {
    "foo": "bar"
  }
}

And the Token Endpoint response:

{
  "accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresAt": 1735689600000
}

See Frontend Integration for how the frontend SDKs use these endpoints.

Secret Rotation

For most SDKs, the secrets setting accepts either a single secret or an array of secrets, each at least 32 characters long. Some SDKs limit the array to three secrets (e.g. Express). When it's an array, the SDK always encrypts with the first secret, and tries each secret in order when decrypting. This lets you change your session secret without logging out every user.

To rotate a secret:

  1. Add the new secret to the front of the array (e.g. [newSecret, oldSecret]) and deploy. Existing sessions still decrypt with the old secret, and every saved session is now encrypted with the new one.
  2. Wait at least maxAge, so every session encrypted with the old secret has expired.
  3. Remove the old secret (e.g. [newSecret]) and deploy.

For example, using the Express Auth SDK:

const sessionOptions = {
  secrets: [process.env.NEW_SESSION_SECRET!, process.env.OLD_SESSION_SECRET!],
  maxAge: 3600,
};

Session Configuration

Session management supports the following settings. Setting names vary by SDK, and SDKs built on a framework's session system configure them through that framework's settings, where the framework's defaults apply.

SettingDescriptionDefault
SecretThe secret used to encrypt and decrypt the session cookie. Must be at least 32 characters. SDKs that support secret rotation also accept multiple secrets.Required
StorageWhere the session is stored. Some SDKs only support an encrypted cookie, while others let your application choose or provide a different session store.Encrypted cookie
Cookie nameThe name of the session cookie.session
Cookie domainThe domain of the session cookie. When not set, the browser only sends the cookie to the exact host that set it.Not set
Cookie pathThe path of the session cookie./
Session lifetimeHow long the session lasts after it was last saved.1 hour
Rolling expirationWhen the session's expiration is extended. Some SDKs extend it on every save, while others follow the framework's own rules.On
SameSiteThe SameSite attribute of the session cookie: Lax, Strict, or None.Lax
SecureWhether the session cookie is only sent over HTTPS. Only disable for local development without HTTPS.On
HttpOnlyWhether JavaScript is blocked from reading the session cookie. Always on in some SDKs.On
CSRF protectionWhether the SDK generates and validates CSRF tokens. Not supported by every SDK.Off
CSRF cookie nameThe name of the CSRF cookie. Only used when CSRF protection is on.CSRF-TOKEN
CSRF cookie domainThe domain of the CSRF cookie. Only used when CSRF protection is on.The session cookie domain

See CSRF Protection for more on the CSRF settings.



Did this page help you?