Token Storage
Redis and in-memory refresh token storage, key formats, rotation, revocation, and test configuration.
Token Storage
TokenStorageInterface tracks refresh tokens for revocation. Access tokens are not tracked because their short TTL is the revocation mechanism.
Why only track refresh tokens
| Token type | TTL | Revocation |
|---|---|---|
| Access token | 15 min | JWT expiry |
| Refresh token | 7 days | JTI storage |
Checking Redis on every API request would add latency to access token validation. The access token TTL keeps the compromise window short.
Refresh tokens require explicit revocation — a 7-day validity window is too long to rely on TTL alone.
RedisTokenStorage
Use Redis in real applications:
use Vortos\Auth\Storage\RedisTokenStorage;
$config->tokenStorage(RedisTokenStorage::class);Key format:
vortos_auth:token:{jti} value: userId, TTL matches token expiry
vortos_auth:user_tokens:{userId} SET of active JTIs for this userAuth keys use the prefix vortos_auth:, separate from your application cache prefix. Running vortos:cache:clear does not affect auth tokens. Users are not logged out when you clear the cache.
InMemoryTokenStorage
Use in-memory storage only for tests and local experiments:
use Vortos\Auth\Storage\InMemoryTokenStorage;
$config->tokenStorage(InMemoryTokenStorage::class);It stores JTIs in a PHP array and enforces TTL lazily when isValid() is called.
Custom storage
For custom storage (e.g. PostgreSQL for audit requirements):
$config->tokenStorage(DbalTokenStorage::class);Your class must implement:
interface TokenStorageInterface
{
public function store(string $jti, string $userId, int $expiresAt): void;
public function isValid(string $jti): bool;
public function revoke(string $jti): void;
public function revokeAllForUser(string $userId): void;
}Token rotation
When a refresh token is used, it is revoked before the new pair is issued:
validate refresh token
→ check Redis: jti exists? yes
→ check expiry: not expired
revoke old jti in Redis
issue new access + refresh pair
→ store new jti in Redis
return new token pairA stolen refresh token cannot be used after it has been used once by the legitimate holder.