docs
  1. Storefront Application
  2. Technical Foundation
  3. Sessions

Sessions

Overview

The SCAYLE Storefront Application leverages robust session management and authentication mechanisms to ensure secure and personalized user experiences. This includes supporting user logins, persistent baskets and wishlists, and seamless Single Sign-On (SSO) capabilities via specifiable Identity Providers (IDPs).

Maintaining User State via Sessions

The Storefront Application maintains stateful sessions, crucial for user login and the persistence of baskets and wishlists. These sessions are designed to be consistent across various servers, thanks to a shared persistent storage provider.

Session Storage

Session data is stored using a shared, persistent, and configurable storage provider, abstracted via Unstorage. Configuration is managed via Nuxt's server storage option. Check Storefront Guide - Storage for detailed information on how to configure the session storage.

The in-memory storage provider should only be used for development.

For production, a reliable persistent storage solution is essential. Refer to the Storefront Guide - Caching for detailed storage configuration.

Session Cookies

The session ID is stored in a cookie, named $session-{shopId} by default. Session cookies are configured as HttpOnly for enhanced security, preventing client-side JavaScript access.

  • The session cookie is shop-based via its name but applies to all requests for that domain, lacking path scope.
  • The session cookie's domain is automatically set to the current domain.

Guest and Logged-In Users

Guest users receive a randomly generated UUID as their session ID. Logged-in users have session IDs that combine their user ID with a random UUID.

Session Configuration

Session storage and cookie serialization are configurable through the session property in the Storefront Application's module configuration within nuxt.config.ts. Configuration can be set globally or per shop, with shop-specific settings taking precedence.

The session.provider configuration option has been removed with scalye/[email protected]; use storage.session instead.

ParameterTypeDescription
session.cookieNamestringThe name used for the session cookie. Defaults to $session-${shopId}.
session.sameSite'none' | 'lax' | 'strict'The sameSite policy to use for the session cookie. Defaults to 'lax'.
session.maxAgenumberThe default maxAge (in seconds) set on the session cookie and default TTL for session store. Defaults to 86400 (one day).
session.secret

string | string[]

The secret used for signing session cookies. If an array is passed, the last value is used for signing new cookies, but all values are used to verify cookies.

This allows to rotate secrets in case your session secret get's leaked.
session.domainstringControls the domain option on the session cookie.

Configuration Example

User-Bound Sessions

Upon successful login, the session ID is updated to incorporate the user ID. Any existing guest user basket and wishlist items are automatically merged into the logged-in user's corresponding data, ensuring continuity of their shopping experience.

RPCContext Session Methods

RPC methods can access and manipulate user session data and control session lifecycle through the RpcContext. Key properties and methods available in the RpcContext include:

MethodDescription
context.user: ShopUserProvides access to the user data saved on the session.
context.updateUser: (user: ShopUser) => voidUpdate the user data saved on the session.
context.destroySession: () => Promise<void>Destroys the current session, logging out the user in the process.
context.destroySessionsForUserId: (userId: number, sessionsToKeep?: string[]) => Promise<void>Destroys all sessions for a specific user, except for those listed in sessionsToKeep.

Securing User Access via Authentication

The Storefront Application supports secure authentication features, including token-based authentication (JWKS), password reset URLs, Identity Providers (IDPs), and app keys for baskets and wishlists. The Storefront Application primarily relies on OAuth to communicate with the SCAYLE Checkout service for core authentication flows.

Token-Based Authentication (JWKS)

Token-based authentication, leveraging JSON Web Key Sets (JWKS), allows you to implement custom login forms directly within the Storefront Application instead of relying solely on forms provided by the Checkout service. The Storefront Application acts as an OAuth client and uses the Get JSON Web Key Set Authentication API endpoint ({OAUTH_API_HOST}/.well-known/jwks.json) for token verification.

Token-Based Authentication Flow

Token Verification

Configuration for OAuth is done via the runtimeConfig.storefront.oauth property in nuxt.config.ts. You'll need to create a new API client using the SCAYLE Panel to obtain your oauth.clientId and oauth.clientSecret.

These configuration values can be overridden via the following environment variables:

OAUTH_API_HOSTURL of the OAuth service.
OAUTH_CLIENT_IDID that the authorization server assigned to this application.
OAUTH_CLIENT_SECRETSecret known only to the application and the authorization server. It is essentially the application’s password.

Protected RPC Methods

Protected RPC methods must implement logic to verify user access based on the access token and user data available in the RpcContext. This involves checking if the user associated with the request (via their user ID in the access token) is authorized to perform the requested data retrieval or action (e.g., matching user IDs against an order). For general user-related actions like changing a password, this is typically handled directly by the underlying SCAYLE Authentication Service.

Password Reset URL

A password reset URL can be manually configured in nuxt.config.ts on a per-shop basis using the runtimeConfig.storefront.shops.{UNIQUE_IDENTIFIER}.auth.resetPasswordUrl property. This URL must include the hash={hash} query parameter.

When the password-forgotten email is sent, the {hash} placeholder in this URL will be replaced with an actual hash, which is required by the password reset process.

Identity Providers (IDPs)

Identity Provider (IDP) support enables Single Sign-On (SSO), simplifying the login process for users by allowing one set of credentials to be used across multiple websites.

The Storefront Application's integrated IDP support consists of two core functionalities:

  • An internal part that runs the useIDP() composable and generates redirect URLs for all configured IDPs.
  • A handleIDPLoginCallback function that performs the actual login process after the user is redirected back from the IDP.

For more information on the underlying APIs, check the Authentication API Guide.

Configure Identity Providers

Available Identity Providers (Google, Facebook, Keycloak, Apple, Okta currently supported) can be configured in nuxt.config.ts globally for all shops, or with shop-specific overrides.

IDP Redirect URL

Redirects to the respective configured IDPs are handled by the useIDP composable. Calling useIDP checks if IDP is enabled, validates configurations, and returns a list of redirect URLs for each IDP based on your shop configuration.

Login with IDP

Once the user clicks on an IDP button, they are redirected to the IDP login page. After successful login, the user is redirected back to the idpRedirectURL (your shop URL) with a code query parameter appended. This code is then used to generate the access token and refresh token.

IDP Authentication Flow

App Keys for Baskets and Wishlists

The appKeys configuration defines how unique keys are generated for baskets and wishlists. These keys are used to create a secure relation between the user (session) and their respective basket or wishlist.

Security Alert: appKeys must remain confidential. Their exposure may enable unauthorized modifications to customer baskets and wishlists.

wishlistKey and basketKey are template strings. When creating the key, the Storefront SDK will replace {shopId} and {userId} with the current shop ID and user ID. It will then hash the result with the chosen hash algorithm. sha256 is recommended as the hash algorithm due to increased security. md5 is only supported to provide backward-compatibility, and its further usage is discouraged.