Cookie security flags: httpOnly, Secure, SameSite
Set appropriate flags on session cookies to prevent vulnerabilities. `httpOnly` prevents client-side JavaScript from accessing the cookie, countering XSS attacks. `Secure` restricts the cookie to HTTPS-only communication. `SameSite` prevents cookies from being sent in cross-site requests, protecting against CSRF attacks. Configure in Express with: `cookie: { secure: true, httpOnly: true, path: '/user', sameSite: true }`.
Session Management definition and requirements
Session Management is a process by which a server maintains the state of an entity interacting with it. Sessions should be unique per user and computationally very difficult to predict. The session identifier can be passed back and forth between client and server.
Include tenant identifier in every tenant-scoped cache key
Classify each cached value as global, tenant-scoped, or user-scoped. Include the tenant identifier in every cache key whose value or authorization varies by tenant. Include every other attribute that changes the result, such as user, locale, feature set, or permission version.
Give intentionally shared cache entries an explicit global namespace
Shared cache entries should be placed in an explicit global namespace and documented with a rationale for why they are safe to share.
Authorize before reading protected cached values
Authorize the request before reading a protected cached value. Cache-key separation does not replace authorization.
Use separate cache instances for strong physical isolation between tenants
For tenants that require stronger physical isolation, use separate cache instances rather than relying solely on key namespacing.
Choose cache TTL and invalidation based on freshness and authorization risk
TTL and invalidation behavior should be chosen from freshness and authorization risk. Immutable, versioned global entries may not require expiry.
Rails session storage defaults to cookie-based without server-side expiration
By default, Rails uses a cookie-based session store with no server-side session expiration, making applications vulnerable to replay attacks. Sensitive information should never be stored in sessions. Best practice: use a database-based session store by configuring: Project::Application.config.session_store :active_record_store
Classify cache audience before caching
Before caching a response or function result, classify its audience: public, tenant-scoped, user-scoped, permission-set, locale, cohort, or request-specific. A cache entry must not be reusable by a broader audience than the data permits.
use cache directive includes arguments and closures in cache key
With use cache, Next.js includes serializable arguments and captured closure values in the generated cache key. Include a verified user, tenant, or other audience dimension when it changes the cached value or a cached authorization decision. When content is identical across authorized callers and authorization is enforced separately before return, do not duplicate the cache merely by identity.
Cache key requirements for protected data
Establish and verify required authorization context before returning protected cached data. Include only verified dimensions that change the cached value or cached authorization decision, such as user ID, tenant ID, permission version, or locale. Do not use a raw cookie or bearer token as a cache key. Do not put user-specific data in a use cache function that has no user-specific input.
Static caches require publicly cacheable data
Use caches that serve a response before per-request application authorization, such as Incremental Static Regeneration (ISR), getStaticProps, or shared CDN caching, only for data the full cache audience may read. Next.js states that getStaticProps data must be publicly cacheable. A server-side data or fetch cache may hold protected content shared by authorized callers when every return path authorizes access and the key separates every content variant.
Avoid shared Cache-Control directives on personalized responses
Do not add shared Cache-Control directives to personalized getServerSideProps responses.
Cache invalidation requires authentication and authorization
Treat cache invalidation as a mutation capability. revalidatePath and revalidateTag can be called from server entry points, while updateTag is limited to Server Actions. Authenticate and authorize callers, derive invalidation target from an authorized object or validate it against constrained application-owned path and tag patterns, and apply abuse controls to externally reachable invalidation handlers. A deliberately global purge should require the correspondingly privileged operation.
Cache stale permissions by invalidating or versioning
After authorization or tenancy changes, prevent reuse under stale permissions by invalidating affected keys or tags, advancing a permission version in the key, or using another bounded expiration strategy.
use cache: private caches in browser memory
use cache: private can read request-time values, but its results are cached in the browser's memory and are still delivered to that browser. The directive documentation does not make over-broad data safe to return.
Test cache with cross-user and cross-tenant identities
For user-, tenant-, or permission-scoped caches, test representative identities with different entitlements: fill the cache as identity A, then request the same route and object identifiers as identity B. Repeat after changing a role or tenant membership. This catches missing audience keys that a positive-path cache test cannot.