Vortos
Authentication

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 typeTTLRevocation
Access token15 minJWT expiry
Refresh token7 daysJTI 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:

config/auth.php
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 user

Auth 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:

config/test/auth.php
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 pair

A stolen refresh token cannot be used after it has been used once by the legitimate holder.

On this page