In this article
August 29, 2025
August 29, 2025

How to implement “Sign out everywhere”

Step-by-step guide to building a secure "sign out of all devices" feature using the WorkOS Sessions API in Node.js.

A familiar feature in modern apps (and one users have come to expect) is the ability to sign out from all devices at once. Picture a user logged into your app on their laptop at work, their phone on the commute, and their tablet at home. At some point, they’ll want a way to hit a single button and instantly log out everywhere. Maybe they’ve lost a device, maybe they’re worried about security, or maybe they just want peace of mind.

This is often referred to as “sign out everywhere” or “sign out of all devices”. The idea is simple: invalidate all of a user’s active sessions at once. This ensures that no matter where the user is logged in, their access is revoked immediately.

With the WorkOS Sessions API, implementing this functionality is straightforward. In this tutorial, we’ll walk through:

  • Why this feature matters.
  • How WorkOS helps implement it cleanly.
  • Step-by-step implementation in Node.js (+ links to docs for other languages like Ruby, Go, etc.).
  • Example code for revoking sessions.

Why “sign out everywhere” matters

Think about this: you’re on vacation, staying at an Airbnb, and you log into Netflix so you can watch a movie. The stay ends, you pack your bags, and check out, but you forget to log out of the TV. A week later, you open Netflix at home and notice a “Recently Watched” row full of Dave’s reality TV choices. Not only is it awkward, it’s a little unsettling.

That’s the classic “I wish I could just sign out everywhere” moment. And it’s not unique to Netflix, it’s a situation many apps need to plan for.

  • Security with peace of mind: Whether it’s an Airbnb TV or a lost phone, users need a panic button that locks down their account instantly. One click, all sessions gone, risk minimized.
  • A user experience people expect: Big names like Netflix, Google, and Slack already set the standard. Offering the same builds trust and makes your app feel polished and reliable.
  • Simplicity for developers: Behind the scenes, session revocation can get messy, tracking logins across browsers, devices, and platforms. Instead of building that logic yourself, the WorkOS Sessions API handles it centrally.

Prerequisites

To follow this tutorial, you will need the following:

  1. A WorkOS account.
  2. A Node.js app (Node 16 or higher) with AuthKit enabled and the WorkOS Node SDK configured (or the SDK for your stack).
  3. Have your app already set up with WorkOS authentication and session creation (detailed steps here).

Let's get started.

Step 1: List all active sessions for the user

First, you’ll fetch all sessions for the current user using the List Sessions endpoint so you can revoke them.

	
// sessions.ts
import { WorkOS } from '@workos-inc/node';
const workos = new WorkOS(process.env.WORKOS_API_KEY!);

// Returns an array of session objects for a given user
export async function listUserSessions(userId: string) {
  const sessions = await workos.userManagement.listSessions(userId);
  return sessions.data; // [{ id, user_id, status, ... }]
}
	

The data array response looks like this:

	
[
    {
      "object": "session",
      "id": "session_01E4ZCR3C56J083X43JQXF3JK5",
      "user_id": "user_01E4ZCR3C56J083X43JQXF3JK5",
      "organization_id": "org_01E4ZCR3C56J083X43JQXF3JK5",
      "status": "active",
      "auth_method": "password",
      "ip_address": "192.168.1.1",
      "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
      "expires_at": "2025-07-23T15:00:00.000Z",
      "ended_at": null,
      "created_at": "2025-07-23T14:00:00.000Z",
      "updated_at": "2025-07-23T14:00:00.000Z"
    }
]
	

This gives you a detailed view of where a user is logged in (user_agent), when the session expires, and other useful information, like IP address and authentication method.

Step 2: Revoke each session

Go through the list of active sessions and revoke each one.

	
// sessions.ts
export async function revokeSessionsById(sessionArray: { id: string }[]) {
  const revocations = sessionArray.map((s) =>
    workos.userManagement.revokeSession({ sessionId: s.id })
  );
  await Promise.allSettled(revocations);
}
	

WorkOS APIs are rate limited to ensure that they are fast for everyone. If you find yourself getting 429 errors, double check your integration to make sure you aren’t making unnecessary requests. For details, see API Reference: Rate limits.

Step 3: Add the new logout endpoint and clear the local session

This is the endpoint your UI calls when the user clicks “Sign out everywhere.” It:

  1. lists sessions
  2. revokes them all, and
  3. clears the local session on the caller
	
// routes/logout-everywhere.ts
import express from 'express';
import cookie from 'cookie';
import { listUserSessions, revokeSessionsById } from '../sessions.js';

const router = express.Router();

router.post('/logout-everywhere', async (req, res) => {
  // However you identify the current user
  const userId = req.user.id;

  try {
    const sessions = await listUserSessions(userId);
    await revokeSessionsById(sessions);

    // Clear local session for THIS device
    res.clearCookie('sessionId', { httpOnly: true, sameSite: 'lax', secure: true, path: '/' });

    res.status(200).json({ message: 'Signed out from all devices.' });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Failed to sign out everywhere.' });
  }
});

export default router;
	

Step 4: Handle revoked sessions on other devices

Other devices won’t know they’re invalid until they try to do something. You have two ways to handle this:

  • Handle it passively, and when a session is found to be invalid, remove it and ask the user to log in again.
  • Monitor the session.revoked event emitted via WorkOS, clear the session, and ask the user to log in again when they try to access the app.

If you choose the latter approach, you have 2 options available for retrieving the revoked session event:

  • Pull it using the Events API
  • Have it pushed to you using webhooks

Option A: Sync with the Events API

To list session.revoked events with the Events API:

	
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS(process.env.WORKOS_API_KEY);

const listOfEvents = await workos.events.listEvents({
  events: [
    'session.revoked',
  ],
});
	

Response:

	
{
  "object": "list",
  "data": [
    {
        "event": "session.revoked",
        "id": "event_04FKJ843CVE8F7BXQSPFH0M53B",
        "data": {
            "object": "session",
            "id": "session_01HSCBECW0D7AY8CA45AYKA64G",
            "user_id": "user_01HQGXWZW8BSHRG3HVK2QF7XBX",
            "organization_id": "org_01HQHCBRRAVQ7N3PX81VKAYXSX",
            "impersonator": {
            "email": "admin@example.com",
            "reason": "Helping a customer fix an issue with their account."
            },
            "ip_address": "192.0.2.1",
            "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
            "created_at": "2024-03-19T21:56:25.080Z",
            "updated_at": "2024-03-19T21:56:25.080Z"
        },
        "created_at": "2024-03-19T21:56:25.080Z",
        "context": {
            "client_id": "project_01EGKAEB7G5N88E83MF99J785F"
        }
    }
  ],
  "list_metadata": {
    "after": "event_01H2GQNMQNH8VRXVR7AEYG9XCJ"
  }
}
	

Retrieving events from the API uses cursor pagination. To fetch the next set of events, provide the ID of the latest processed event in the after parameter.

The after param contains the object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with "obj_123", your subsequent call can include after="obj_123" to fetch a new batch of objects after "obj_123".

For more details and code samples, see Sync data using the Events API.

Option B: Sync with webhooks

To sync with webhooks you have to:

  1. Create your endpoint to receive webhook events.
  2. Register your endpoint with WorkOS.
  3. Process the events received from WorkOS.

Set up your webhook endpoint

Create a public endpoint that WorkOS can send events to. This endpoint should use HTTPS and should accept POST requests with the workos-signature header.

	
import type { NextApiRequest, NextApiResponse } from 'next';

export default (req: NextApiRequest, res: NextApiResponse) => {
  if (req.method === 'POST') {
    const payload = req.body;
    const sigHeader = req.headers['workos-signature'];

    // Verify the signature and process the event
    res.status(200).end();
  }
};
	

Register your endpoint

Set and save the webhook URL in the WorkOS dashboard > Webhooks, so WorkOS knows where to deliver the events. Your webhook endpoints should only be configured to receive the ones required by your integration. Receiving all event types can put undue strain on your servers and is not recommended.

Process the events received

In order to avoid unnecessary retry requests hitting your webhook handler, we recommend using two concurrent processes for handling events: one for receiving the event, and the other for processing it.

On receiving an event, you should respond with an HTTP 200 OK to signal to WorkOS that the event was successfully delivered. Otherwise, WorkOS will consider the event delivery a failure and retry up to 12 times, with exponential backoff over 3 days. You do not need to signal to WorkOS whether or not the event was processed successfully.

Before processing the request payload, verify the request was sent by WorkOS and not an unknown party. WorkOS includes a unique signature in each webhook request that it sends, allowing you to verify the authenticity of the request. In order to verify this signature, you must obtain the secret that is generated for you when you set up your webhook endpoint in the WorkOS dashboard. Ensure that this secret is stored securely on your webhook endpoint server as an environment variable.

The SDKs provide a method to validate the timestamp and signature of a webhook. The parameters are the payload (raw request body), the request header, and the webhook secret.

	
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS(process.env.WORKOS_API_KEY);

const webhook = await workos.webhooks.constructEvent({
  payload: payload,
  sigHeader: sigHeader,
  secret: process.env.WEBHOOK_SECRET,
});
	

For more implementation details and code samples, see Sync data with webhooks.

Step 5: View revoked sessions

To view the revoked sessions for a user, go to WorkOS dashboard > Users, select the user, and click on Sessions.

Best practices & implementation tips

  • Always revoke all existing sessions when a password is changed.
  • Pair session metadata (IP, device, last active time) with heuristics to selectively revoke risky sessions.
  • Provide a UI where users can view and revoke their own sessions, just like Google or Facebook.
  • After revocation, ensure your app properly redirects users with invalid tokens back to the login flow.

Get started with the Sessions API

Whether you’re tightening password reset flows, adding user-facing “sign out everywhere” functionality, or building admin-level security controls, the Sessions API gives you everything you need to manage sessions with enterprise-grade precision.

Head to the documentation to get started with the WorkOS Sessions API today.

This site uses cookies to improve your experience. Please accept the use of cookies on this site. You can review our cookie policy here and our privacy policy here. If you choose to refuse, functionality of this site will be limited.