How to Revoke Tokens with a Blacklist Set in Python

A minimal TokenBlacklist class using a Python set to revoke, batch-revoke, check, and remove expired tokens for simple token invalidation.

Easy Python 3.9+ Aug 9, 2026 Auth & security at scale 13 views 0 copies

Python code

30 lines
Python 3.9+
import time

class TokenBlacklist:
    def __init__(self):
        self.blacklisted_tokens = set()

    def revoke(self, token):
        self.blacklisted_tokens.add(token)
        print(f"Token {token} revoked. Blacklist size: {len(self.blacklisted_tokens)}")

    def revoke_batch(self, tokens):
        before = len(self.blacklisted_tokens)
        self.blacklisted_tokens.update(tokens)
        print(f"Revoked {len(tokens)} tokens. Blacklist grew from {before} to {len(self.blacklisted_tokens)}")

    def is_revoked(self, token):
        return token in self.blacklisted_tokens

    def remove_expired(self, ttl=3600):
        current_time = time.time()
        expired = {t for t in self.blacklisted_tokens if t.endswith(str(int(current_time - ttl)))}
        self.blacklisted_tokens.difference_update(expired)
        print(f"Removed {len(expired)} expired tokens. Remaining: {len(self.blacklisted_tokens)}")

if __name__ == "__main__":
    bl = TokenBlacklist()
    bl.revoke("jwt-token-abc123")
    bl.revoke_batch(["jwt-token-def456", "jwt-token-ghi789"])
    print("Is revoked:", bl.is_revoked("jwt-token-abc123"))
    bl.remove_expired()

Output

stdout
Token jwt-token-abc123 revoked. Blacklist size: 1
Revoked 2 tokens. Blacklist grew from 1 to 3
Is revoked: True
Removed 0 expired tokens. Remaining: 3

How it works

This works because Python sets provide O(1) average-time membership checks and insertion, making is_revoked fast even with many tokens. The revoke and revoke_batch methods add token strings to the set, guaranteeing uniqueness automatically. remove_expired uses a set comprehension to find tokens whose timestamp suffix matches the current TTL window, then removes them in bulk with difference_update. The time.time() import is only used for the mock expiry check, showing how you could layer real timestamps onto token strings. For production, you would store actual expiry timestamps (e.g., in a tuple) rather than encoding them in the token string.

Common mistakes

  • Using a list instead of a set, which makes membership checks O(n).
  • Forgetting to persist the blacklist across restarts (this example is in-memory only).
  • Encoding expiry in the token string as a hack; real systems store explicit expiry times.
  • Not cleaning expired tokens, causing unbounded memory growth.

Variations

  1. Store tokens as tuples `(token, expiry_time)` in a set and check expiry with datetime comparisons.
  2. Use Redis with TTL keys for a distributed, auto-expiring blacklist.

Real-world use cases

  • Invalidating JWT tokens on user logout or password change within a single service.
  • Implementing a simple in-memory blacklist for an API gateway during testing or mock development.
  • Providing a lightweight revocation check for short-lived access tokens in microservices.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Auth & security at scale

Related tutorials and quizzes for this topic.