HelloJohn / docs
Sessions

Multi-Device Sessions

How HelloJohn handles multiple active sessions per user across devices and browsers.

Multi-Device Sessions

HelloJohn supports multiple concurrent sessions per user — one per device, browser, or app instance. This lets users stay signed in on their phone, laptop, and work computer simultaneously.

How It Works

Each sign-in creates an independent session with its own refresh and access tokens. Sessions are tracked with device metadata:

{
  "id": "ses_01HABCDEF999888",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
  "ip_address": "203.0.113.42",
  "country": "US",
  "device_type": "desktop",
  "created_at": "2024-01-15T10:30:00Z",
  "last_active_at": "2024-01-20T08:15:00Z"
}

Listing Sessions

Use the Sessions API to list all active sessions for the current user, or for any user (admin):

# As a backend admin — list all sessions for a user
curl "https://api.hellojohn.dev/v1/sessions?user_id=usr_01HABCDEF123456" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321"

Showing Sessions in Your UI

A common pattern is a "Manage active sessions" page where users can see and revoke individual sessions:

import { useHelloJohn } from "@hellojohn/react";

function SessionManager() {
  const { sessions, revokeSession } = useHelloJohn();

  return (
    <ul>
      {sessions.map((session) => (
        <li key={session.id}>
          <span>{session.device_type} — {session.country}</span>
          <span>Last active: {new Date(session.last_active_at).toLocaleDateString()}</span>
          {!session.current && (
            <button onClick={() => revokeSession(session.id)}>
              Sign out
            </button>
          )}
        </li>
      ))}
    </ul>
  );
}

The SDK marks the current session with session.current: true so you can exclude it from the "sign out" button.

Revoking a Specific Session

Let users sign out of a specific device:

curl -X DELETE "https://api.hellojohn.dev/v1/sessions/ses_01HABCDEF999888" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321"

Revoking All Sessions

Sign a user out of all devices — useful after password change or security events:

curl -X DELETE "https://api.hellojohn.dev/v1/sessions?user_id=usr_01HABCDEF123456" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321"

Response:

{ "revoked": 4 }

Limiting Sessions Per User

You can configure a maximum number of concurrent sessions. When exceeded, the oldest session is revoked automatically:

curl -X PATCH "https://api.hellojohn.dev/v1/admin/config" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "X-Tenant-ID: tnt_01HABCDEF654321" \
  -H "Content-Type: application/json" \
  -d '{"max_sessions_per_user": 5}'

Detecting Suspicious Sessions

You can monitor for sessions with unexpected IP addresses or locations. The country and ip_address fields help identify anomalies:

// Example: flag sessions from unusual countries
const recentSessions = await hj.sessions.list({ user_id: userId });
const homeCountries = ["US", "CA"];

const suspicious = recentSessions.filter(
  (s) => !homeCountries.includes(s.country)
);

if (suspicious.length > 0) {
  // Notify user or trigger MFA re-verification
}

On this page