Ephemeral Sessions
Auth0 "Manage Sessions with Actions" · api.session.setCookieMode()
Every login here is treated as ephemeral
Unlike a picker that asks the browser to self-report "is this a shared device" (an unauthenticated, client-supplied signal not worth trusting for anything security-relevant), this is a dedicated client — think a kiosk app, or a step-up action surface for something sensitive. A Post-Login Action unconditionally applies ephemeral treatment to every session it creates:
api.session.setCookieMode('non-persistent')— the Auth0 AS session cookie is dropped when the browser closes.setExpiresAt/setIdleExpiresAt— 90s absolute, 30s idle, tenant-side.- No
offline_accessscope — no refresh token is ever minted, so there is no standing credential once the short-lived tokens expire.
Security Implications
Strengths
- No client-supplied trust signal to abuse — this is a dedicated client that unconditionally treats every login as ephemeral via a Post-Login Action, matching a realistic architecture (a kiosk app, a step-up/high-risk action surface) rather than one shared app dynamically trusting a browser-asserted "is this a shared device" flag.
- Ephemeral treatment applies end-to-end, not just tenant-side: api.session.setCookieMode('non-persistent') + setExpiresAt/setIdleExpiresAt shorten the Auth0 AS session, and this app's own session cookie (absoluteDuration/inactivityDuration) is independently configured to the same window — the two are genuinely separate mechanisms and both are addressed here.
- No offline_access scope requested, so no refresh token — a standing, reusable credential — is ever minted for this client. Once the short-lived access/ID token expires, there is nothing left to silently renew with.
- Session state is independently verifiable via the Session Management API (cookie.mode, expires_at, idle_expires_at) rather than something the app just claims happened.
Risks & Considerations
- non-persistent cookie mode is a browser-hygiene control, not revocation — the session is fully valid and usable for its entire (short) lifetime; it just does not survive a browser restart. Anyone who keeps the browser open indefinitely gets none of the cookie-mode protection, which is exactly why this demo also tightens setExpiresAt/setIdleExpiresAt rather than relying on cookie mode alone.
- Dropping offline_access is the right trade-off for a kiosk/step-up client, but it is a trade-off, not a free win — a legitimate long-running session that just needs occasional silent renewal would be the wrong place to blanket-apply "no refresh token".
- The two separate session lifetimes (Auth0 AS-side vs. this app's own cookie) only stay aligned because both were explicitly configured to match. A team that only touches the Action's api.session calls and leaves the app's own session.absoluteDuration at its 3-day default would ship a demo that looks ephemeral in the Management API panel but isn't, in practice, for the app itself.
Hardening Checklist
- If a shared app genuinely needs to serve both regular and shared-device users, decide "is this a shared device" server-side from a real signal (device posture, admin/org policy, a risk engine) — never a client-supplied request parameter. This demo avoids the question entirely by giving shared-device flows their own dedicated client instead.
- Always pair setCookieMode('non-persistent') with setExpiresAt/setIdleExpiresAt; the cookie-mode change alone is cosmetic without a tight backing lifetime.
- When shortening session lifetime for a use case like this, audit both halves — the Auth0-side session and whatever session mechanism the app itself uses — rather than assuming one implies the other.
- For genuine hijack detection, extend this with api.session.revoke() plus event.session.device.initial_ip/initial_asn comparisons against the current request — not built into this demo, but a natural next step on the same APIs.