Access tokens are short-lived. Use the refresh method to obtain a new one without requiring the user to log in again. The SDK handles caching and prevents concurrent refresh calls across browser tabs automatically.
How is the refresh flow secured?
The refresh flow is protected by DPoP (Demonstration of Proof-of-Possession). The SDK generates a cryptographic key pair and signs each refresh request with a proof that binds the request to the client. This protects against:
Token theft — A stolen refresh cookie is unusable without the private key, which is bound to the browser and never transmitted
Token replay — Each DPoP proof includes a unique identifier and timestamp, preventing reuse
Man-in-the-middle attacks — The proof binds to the HTTP method and URL, so it cannot be replayed against a different endpoint
Token export — The key pair is non-extractable, meaning it cannot be copied from the browser to another device
const { user } = await client.refresh();// user.accessToken contains the new JWT// user.profile contains the user profile data
To force the next refresh call to hit the backend (bypassing the local cache), invalidate the cache first:
await client.invalidateCache();
Try it
In the login App.jsx above, add decode to your import (import { ..., decode } from "@prelude.so/js-sdk") and replace the article block with:
Use revokeSessions to revoke sessions. The target parameter controls which sessions are revoked:
Target
Description
"all"
Revoke all sessions, including the current one.
"others"
Revoke all sessions except the current one.
"mine"
Revoke the current session only.
"session"
Revoke a specific session by ID.
// Revoke all sessionsawait client.revokeSessions("all");// Revoke all other sessionsawait client.revokeSessions("others");// Revoke the current sessionawait client.revokeSessions("mine");// Revoke a specific session by IDawait client.revokeSessions("session", sessionId);
Try it
Building on the list sessions example above, add revocation controls. Replace src/App.jsx with: