Join our Newsletter — 33% off our NHI Course
Home› FAQ› Authentication, Authorisation & Trust› How should Rails teams implement a sealed session…
Authentication, Authorisation & Trust

How should Rails teams implement a sealed session flow for hosted authentication without leaking refresh tokens into the browser?

← Back to all FAQ
By NHI Mgmt Group Editorial Team Updated September 30, 2026 Domain: Authentication, Authorisation & Trust

Store the session as one opaque, encrypted cookie and keep the refresh token out of readable client storage. Exchange the authorization code server side, seal the resulting session immediately, and write only the sealed value to an HttpOnly cookie. On each request, load and authenticate that seal in the server layer, then refresh it when needed before continuing the response.

Why a sealed session flow belongs on the server side

The core design choice is to treat the browser as a delivery channel for an opaque session, not as a place to hold refresh capability. That means the authorization code is exchanged server side, the resulting session state is sealed immediately, and the browser only receives an HttpOnly cookie containing that sealed value. The browser can present the cookie, but it should not be able to read or unwrap the refresh material inside it.

This pattern reduces exposure from XSS, local inspection, extension abuse, and accidental client-side logging. It also keeps token handling inside the trust boundary where the application can enforce rotation, expiry, and revalidation consistently.

For teams implementing OAuth-based hosted authentication, the most relevant standard is RFC 6749: The OAuth 2.0 Authorization Framework, because the code exchange and downstream token handling must stay aligned with the intended server-mediated flow.

What “sealed session” means in practice

A sealed session is not just a signed cookie with a few claims. It is a server-managed session record, encrypted or otherwise protected so the browser cannot recover the refresh token or other sensitive session material. The cookie should carry only the sealed blob, not the raw token, not a readable JSON payload, and not enough state for client-side replay decisions.

In a Rails app, this usually means the session boundary should be established after the code exchange and before the response leaves the server. If the application needs to refresh access later, that refresh happens by reopening the sealed session in the server layer, using the protected refresh material there, then resealing the updated session before the browser sees the next response.

The implementation should be aligned with modern token guidance such as RFC 9700: Best Current Practice for OAuth 2.0 Security, and with session handling guidance from OWASP ASVS, which both reinforce tight server-side control over token and session handling.

How Rails teams should structure the request lifecycle

The request lifecycle should be simple: authenticate the user or workload server side, load the sealed session from the cookie, validate it in the Rails layer, and refresh it only when the server determines the session needs renewal. The browser should never become the place where refresh logic, token substitution, or token persistence is performed.

That also means the cookie must be protected with HttpOnly and sent only over secure transport, because the whole point of the seal is defeated if client-side JavaScript can read the value or if the cookie can be intercepted in transit. If the session contains long-lived privilege or refresh authority, the server should treat it as sensitive credential material and rotate or reissue it on a short, disciplined cadence.

For practitioner-oriented hardening of the session boundary, Token and Session Security Guide is directly relevant because it covers refresh tokens, session cookies, replay resistance, and token lifetimes in the same control plane.

Risk and Threat Considerations

The main risk is that a refresh token becomes browser-recoverable, which turns a normal web session into a durable credential theft problem. Once a long-lived refresh token is exposed to client storage, attackers can often replay it outside the browser, extend access beyond the original session, and bypass controls that were meant to protect interactive sign-in.

Failure mechanism: The application places refresh capability in readable client storage, or exposes enough session state in the browser to reconstruct or reuse the token. XSS, malicious extensions, logging, or script injection can then lift the token and enable session replay from another device or network.

Impact: Attackers gain persistent access that survives password resets, MFA challenges, and normal browser logout. The result is usually account takeover, silent token replay, and a much larger blast radius than a short-lived access token would create.

The threat is well illustrated by real-world token theft patterns such as Salesloft OAuth token breach and CitrixBleed exploitation 2023, both of which show how stolen session or OAuth material can outlive the original sign-in event.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

OWASP ASVS provides the primary governance reference for this topic.

FrameworkControl / ReferenceRelevance
OWASP ASVSV7 — Session ManagementThe answer depends on secure session handling and browser-facing session containment.
V10 — OAuth and OIDCHosted authentication and authorization-code handling are OAuth/OIDC concerns.
V9 — Self-contained TokensSealed session cookies behave like protected token carriers that must resist disclosure.
Recommendation — Enforce HttpOnly, Secure, and server-side session control for browser sessions. Verify OAuth/OIDC flows keep sensitive tokens out of client-readable storage. Protect sealed session values from disclosure and replay across requests.

Practitioner Guidance

What to verify: Confirm that the browser only ever receives an opaque cookie value, and that the refresh token is stored only inside server-managed session state. If any response body, client cache, front-end store, or JavaScript path can recover the refresh token, the design is not sealed.

Decision rule: If the credential can be used to mint new access without a fresh interactive login, treat it as server-side secret material and keep it out of readable client storage. If the browser needs visibility into the session, expose only non-sensitive display state, never the refresh capability itself.

What good looks like: A request can be served, reauthenticated, and refreshed entirely from the server layer while the browser remains unaware of the underlying refresh token. Session renewal should be observable in logs and metrics, but the token itself should never appear in client-readable form.

Common mistake: Teams often encrypt the cookie and then assume that makes it safe to expose the whole session to the browser. Encryption helps only if the browser receives a sealed blob it cannot open; it does not justify storing raw refresh data in local storage, a readable cookie, or front-end state.

Practitioner takeaway: The browser should carry a sealed presentation of session state, while all refresh authority stays in the server trust boundary where it can be rotated, invalidated, and audited without exposing reusable credentials to client code.

Deepen Your Knowledge

Sign up to our weekly newsletter — get 33% off our NHI Foundation Level Course

    NHIMG Editorial Note
    Reviewed and updated by the NHIMG editorial team on September 30, 2026.
    NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org