I’m working on a microservices-based project where each service is a separate PHP application. They all rely on JWT for authentication and authorization. The tricky part is revoking (or blacklisting) tokens so that when one service revokes a token, all the others immediately recognize it as invalid.
Right now, each service maintains its own blacklist in a local database. That works well enough until one service invalidates a token while others remain unaware for some time. We’ve considered using a shared cache (like Redis) or a central database for blacklists, but we’d like to avoid creating a single point of failure or a significant bottleneck if that shared component goes down.
Another option we looked at was publishing revocation events through a message broker (like RabbitMQ or Kafka), but that still introduces overhead and depends on every service reliably receiving those events, even if one is temporarily offline. We also tried issuing short-lived tokens so they expire quickly on their own, but that doesn’t really help if you need to revoke one immediately for security reasons.
Below is a simplified code snippet (using the firebase/php-jwt library) showing how a service checks if a token is blacklisted:
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
function isBlacklisted(string $jti): bool
{
// This function queries a local database
// that stores blacklisted jti values
return false; // Placeholder
}
$jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
$secretKey = 'MY_SECRET_KEY';
try {
// Decode and verify the signature
$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
// If the token has a jti (JWT ID), check if it's blacklisted
$jti = $decoded->jti ?? null;
if ($jti && isBlacklisted($jti)) {
throw new Exception('Token has been revoked');
}
// Token is valid and not blacklisted; proceed
echo "Token is valid!";
} catch (Exception $e) {
// Handle invalid or revoked token
echo "Invalid or revoked token!";
}
The question is: How can we keep all services in sync about revoked tokens without depending on a centralized data store or service? If anyone has faced a similar scenario or found a creative workaround, I’d really appreciate any insights or suggestions.
Thanks!