Sessions & Tokens
Session duration, persistence, and automatic permission refresh.
Sessions are managed automatically by the SDK.
Step by step, with screenshots: session lifetime and trusted devices, and the Devices screen your users see.
| Behavior | Detail |
|---|---|
| Session duration | 30 days by default - configurable per session, capped at 180 days |
| Permission sync | hourly - role changes from the dashboard update automatically |
| Persistence | Store the session ID in a cookie or localStorage |
Session storage callbacks
Your SaaSOSProvider auth config takes three callbacks - nested under auth.callbacks - to persist the session. See the Installation page for the full provider setup.
// In your SaaSOSProvider auth config
auth={{
clientId: 'your-client-id',
redirectUrl: '/callback',
callbacks: {
getSession: async () => localStorage.getItem('sessionId'),
handleAuthentication: async (code) => {
const res = await fetch('/api/auth/verify', {
method: 'POST',
body: JSON.stringify({ code }),
});
const data = await res.json();
return { sessionId: data.sessionId };
},
onSignOut: async () => localStorage.removeItem('sessionId'),
},
}}The three callbacks:
getSession- Return the stored session ID (from a cookie or your backend)handleAuthentication- Called after sign-in with the auth code. Exchange it for a session on your backend.onSignOut- Clear the stored session
Where to store the session ID
You choose how to persist the session ID. Each option has trade-offs:
| Approach | Security | Setup | Best for |
|---|---|---|---|
| HttpOnly cookie (recommended) | Immune to XSS - JavaScript cannot read it | Requires a backend route to set the cookie | SPAs with a Node.js backend |
| localStorage | Vulnerable to XSS - any script on the page can read it | One line - localStorage.setItem() | Quick prototypes, internal tools |
| Hybrid | HttpOnly cookie for session + localStorage for UI state | More complex | Production apps needing both security and client-side state |
Warning
If your app handles sensitive data (billing, PII), use HttpOnly cookies. localStorage is convenient for prototypes but exposes the session to cross-site scripting attacks.
Devices and active sessions
The SDK tracks the devices a user signs in from and the live sessions on each. Users can review their devices, rename them, and sign out individual sessions or entire devices.
Drop-in components - <Sessions /> lists live sessions with a revoke action; <Devices /> lists devices with rename, sign-out, and remove actions. Both are session-authed and need no config beyond SaaSOSProvider:
import { Devices, Sessions } from '@buildbase/sdk/react';
function SecurityPage() {
return (
<>
<Sessions />
<Devices />
</>
);
}Headless hooks - useSessions() and useDevices() return the same data plus actions for a custom UI:
import { useSessions } from '@buildbase/sdk/react';
function ActiveSessions() {
const { sessions, loading, revoke } = useSessions();
if (loading) return <p>Loading…</p>;
return (
<ul>
{sessions.map((s) => (
<li key={s.id}>
{s.device?.name ?? s.userAgent} — {s.ip}
{!s.current && <button onClick={() => revoke(s.id)}>Sign out</button>}
</li>
))}
</ul>
);
}Direct API access - useSessionsApi() and useDevicesApi() return memoized client instances:
| Client | Methods |
|---|---|
SessionsApi | list() → ISessionView[], revoke(id) |
DevicesApi | list() → IDeviceView[], rename(deviceId, name), signOut(deviceId), forget(deviceId) |
signOut(deviceId) revokes every live session on a device but keeps it in the list as signed out; forget(deviceId) also removes the device entirely. revoke(id) takes the session's public handle (ISessionView.id), not the raw session ID.
To end the caller's own session use signOut() from useSaaSAuth(), and to end every session a user has use signOut({ everywhere: true }) - see sign in and sign out.
The built-in settings dialog includes security and devices screens - open them with openWorkspaceSettings('security') or openWorkspaceSettings('devices') from useSaaSAuth().
How recently the session signed in
A session remembers when its person last proved who they are, and how. useSaaSAuth().session.authTime is that moment, ISO 8601: the sign-in, or a later re-confirmation. session.amr lists the methods as RFC 8176 values, such as ['pwd', 'mfa']. Two-step sign-in lists what a second step adds. A session made from an API key has no authTime and never counts as recent.
Removing a sign-in method or deleting the account needs a session that proved itself in the last 10 minutes. An older one re-confirms on the hosted page and keeps going, without signing out: see Confirm it's you.
Common questions
Role changes not taking effect? Permissions refresh hourly. Sign out and back in for immediate effect.
Session lost on refresh? Make sure your getSession callback reads from persistent storage, not memory.
Session expired? Sessions last 30 days by default and can be configured to last up to 180 days. Trusted devices and the org session policy also affect expiry. When a session expires, the user must sign in again.
Next Steps
- Protected Routes - Guard routes based on auth state.
- Workspaces Overview - Multi-tenant workspaces.