Session Upgrade

JWT tokens are ideal for REST APIs but add overhead to high-frequency socket communication. Altruist provides a session upgrade flow: login with JWT over HTTP, then upgrade to a lightweight session token for real-time connections.

The Flow

Loading diagram...
StepWhat HappensToken
1Login via HTTPJWT issued
2Upgrade via HTTPSession token issued, JWT invalidated
3Connect to socketSession token as Bearer

Setup

1. Auth Controller (provides login + upgrade)

[ApiController]
[Route("/auth")]
public class AuthController : JwtAuthController
{
    public AuthController(
        IJwtTokenValidator validator,
        ILoginService loginService,
        TokenSessionSyncService syncService,
        IJwtTokenIssuer issuer,
        IAuthService authService,
        ILoggerFactory loggerFactory)
        : base(validator, loginService, syncService, issuer, authService, loggerFactory)
    {
    }
}

2. Game Portal (protected with SessionShield)

[Portal("/game")]
[SessionShield]
public class GamePortal : AltruistPortal
{
    [Gate("move")]
    public async Task OnMove(MovePacket packet, string clientId)
    {
        // Only clients with valid session tokens reach here
    }
}

3. Client Flow

# Step 1: Login → get JWT
curl -X POST http://localhost:3000/auth/login/unamepwd \
  -H "Content-Type: application/json" \
  -d '{"username": "hero", "password": "secret123"}'
# → { "accessToken": "eyJ...", "refreshToken": "eyJ..." }

# Step 2: Upgrade JWT → get session token
curl -X POST http://localhost:3000/auth/upgrade \
  -H "Authorization: Bearer eyJ..." \
  -H "Content-Type: application/json" \
  -d '{"token": "eyJ..."}'
# → { "accessToken": "31c7e8ef-...;session", "refreshToken": "eef813a8-..." }

# Step 3: Connect to socket with session token
# WebSocket: ws://localhost:3000/ws with Authorization: Bearer 31c7e8ef-...
# TCP: send session token in initial handshake

Session Token Response

{
  "accessToken": "31c7e8ef-1541-4499-b2a9-577b80c160f1;session",
  "refreshToken": "eef813a8-714a-43ed-82d9-41fdb832cd1c;session",
  "accessExpiration": "2025-04-16T21:14:42Z",
  "refreshExpiration": "2025-04-23T20:14:42Z"
}

Why Upgrade?

JWTSession Token
ValidationDecode + verify signature (CPU-heavy)Cache lookup (fast)
Size~800+ bytes~40 bytes (UUID)
RevocationDifficult (stateless)Instant (delete from cache)
Best forHTTP REST APIsHigh-frequency socket messages

Note:

Session tokens are validated via a cache lookup — no cryptographic verification on every packet. For a game server processing thousands of packets per second, this is significantly faster than JWT validation.

Hooks

Override hooks on JwtAuthController for custom logic:

protected override UpgradeAuthRequest OnUpgrade(UpgradeAuthRequest context, string clientId)
{
    // Modify context before upgrade
    return context;
}

protected override async Task OnUpgradeSuccess(UpgradeAuthRequest context, string clientId, IIssue issue)
{
    // Create game session, load player data, etc.
}

protected override async Task OnUpgradeFailed(UpgradeAuthRequest context, string clientId)
{
    // Log failed upgrade attempt
}

Config

altruist:
  security:
    mode: "jwt"
    key: "your-base64-secret-key"
  persistence:
    cache:
      provider: redis    # Session tokens stored in cache (redis recommended for production)

Note:

Session tokens are stored in the cache provider. Use Redis for production — inmemory cache loses all sessions on server restart.