DEV Community

Cover image for How I Implemented Logout From One Device and All Devices in My Auth System
Anish Hajare
Anish Hajare

Posted on

How I Implemented Logout From One Device and All Devices in My Auth System

"Logout" sounds like one of the easiest features in authentication.

It's just a button, right? ๐Ÿ˜„

That's what I thought too.

But once I started building a more realistic auth system, I realized logout is only simple if you don't ask too many questions.

Questions like:

  • Does logout affect only this device?
  • What happens to other active sessions?
  • How do I support logout from all devices?
  • How do I make revoked sessions stop working right away on protected routes?

That's when I learned something important:

Real logout is not just about clearing a cookie. It's about telling the backend to stop trusting a session.

So in this project, I built both:

  • Logout from the current device
  • Logout from all devices

And it taught me a lot about session design.


๐Ÿค” Why Logout Is Harder Than It Looks

In simple auth demos, logout often means:

  • Delete token from local storage
  • Clear cookie
  • Redirect to login

That works on the client side.

But from the backend's point of view, that is not always enough.

If the server still trusts the session behind that token, then logout is only partially real.

That's the gap I wanted to close.


๐Ÿง  The Key Idea: Sessions Live on the Server

To make logout meaningful, I tracked sessions in the database.

Each session stores things like:

  • Which user it belongs to
  • A hashed refresh token
  • IP address
  • User agent
  • Whether the session is revoked
  • When it was revoked

That makes logout a backend-controlled action instead of just a frontend cleanup step.


๐Ÿšช Logout From the Current Device

For current-device logout, the goal is simple:

  • Invalidate only the session tied to the current refresh token
  • Leave the user's other devices alone

So the server looks up the session connected to the refresh token, marks it as revoked, and stops trusting it.

Here's the main logic:

export async function revokeCurrentSession(refreshToken) {
  const session = await sessionModel.findOne({
    refreshTokenHash: hashValue(refreshToken),
    revoked: false,
  });

  if (!session) {
    throw new AppError(400, "Invalid refresh token");
  }

  session.revoked = true;
  session.revokedAt = new Date();
  await session.save();
}
Enter fullscreen mode Exit fullscreen mode

That gives logout real meaning.

It's not just "remove the cookie."
It's "this session should no longer be accepted."


๐ŸŒ Logout From All Devices

This feature was even more interesting.

A user might want to:

  • Sign out everywhere after suspicious activity
  • Clear old sessions across devices
  • End all active logins at once

So I added a logout-all flow.

In this implementation, the backend uses the refresh token cookie to identify the user, then revokes all active sessions for that account.

export async function revokeAllSessions(refreshToken) {
  const decoded = jwt.verify(refreshToken, config.JWT_SECRET);

  await sessionModel.updateMany(
    {
      userId: decoded.id,
      revoked: false,
    },
    { revoked: true, revokedAt: new Date() },
  );
}
Enter fullscreen mode Exit fullscreen mode

That means every active session for that user becomes revoked.


๐Ÿ” What About Existing Access Tokens?

This was the part that made the design much more interesting.

Revoking refresh tokens alone is not enough.

A user may still have an access token that has not expired yet.

So I tied access tokens to a sessionId and had protected routes check whether the related session is still active.

That means protected routes do not only verify the JWT itself.

They also check:

  • Does the session still exist?
  • Does it belong to this user?
  • Has it been revoked?

So it's more accurate to say this:

Existing access tokens stop working on protected routes because the server checks whether their session is still active.

That's what makes session revocation effective in practice.


๐Ÿงช Testing This Was Super Important

Logout is one of those features that feels correct until you actually test it.

So I added tests for behaviors like:

  • Logout should revoke only one session
  • Logout-all should revoke every active session
  • Protected routes should reject access tied to revoked sessions

That last part matters a lot.

Because logout-all is only meaningful if revoked sessions are actually rejected later.

Testing helped confirm that the behavior matched the promise.


๐Ÿ˜… What Was Challenging

The tricky part wasn't writing the endpoint itself.

It was making the whole system agree on what logout means.

That included:

  • Refresh token lookup
  • Session revocation
  • Protected route validation
  • Multi-device behavior
  • Making sure one-device logout doesn't affect others

This was one of those features that sounded small in product terms, but touched a lot of auth architecture underneath.


๐Ÿ“š What I Learned

A few things became really clear while building this:

  • Clearing a cookie is not the same as invalidating a session
  • Server-side session tracking makes logout much stronger
  • Logout-all is really a session revocation problem
  • Protected routes need session awareness if you want revoked sessions to stop working
  • Multi-device auth adds complexity very quickly

My biggest takeaway was this:

If your backend cannot tell whether a session is still trusted, logout is only partially real.

That idea changed the way I think about authentication.


๐ŸŽฏ Final Thoughts

This feature taught me that logout is not boring at all.

It's actually one of the most revealing parts of an auth system, because it forces you to answer:

  • Who is authenticated right now?
  • Which session is still trusted?
  • How does trust get revoked?

If you're building your own auth system, I highly recommend thinking beyond "clear the cookie."

Because once users have multiple devices, logout becomes much more than a frontend action.


Have you implemented logout-all in your own auth flow? Drop a comment below and ask questions if you have any. I'd love to talk about it. ๐Ÿ’ฌ

Top comments (0)