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.
Python code
30 linesimport 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
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
- Store tokens as tuples `(token, expiry_time)` in a set and check expiry with datetime comparisons.
- 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
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.