feat(#284): Reduce timestamp validation window to 60s with replay attack prevention
Security improvements: - Reduce timestamp tolerance from 5 minutes to 60 seconds - Add nonce-based replay attack prevention using Redis - Store signature nonce with 60s TTL matching tolerance window - Reject replayed messages with same signature Changes: - Update SignatureService.TIMESTAMP_TOLERANCE_MS to 60s - Add Redis client injection to SignatureService - Make verifyConnectionRequest async for nonce checking - Create RedisProvider for shared Redis client - Update ConnectionService to await signature verification - Add comprehensive test coverage for replay prevention Part of M7.1 Remediation Sprint P1 security fixes. Fixes #284 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
54
apps/api/src/common/providers/redis.provider.ts
Normal file
54
apps/api/src/common/providers/redis.provider.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Redis Provider
|
||||
*
|
||||
* Provides Redis/Valkey client instance for the application.
|
||||
*/
|
||||
|
||||
import { Logger } from "@nestjs/common";
|
||||
import type { Provider } from "@nestjs/common";
|
||||
import Redis from "ioredis";
|
||||
|
||||
/**
|
||||
* Factory function to create Redis client instance
|
||||
*/
|
||||
function createRedisClient(): Redis {
|
||||
const logger = new Logger("RedisProvider");
|
||||
const valkeyUrl = process.env.VALKEY_URL ?? "redis://localhost:6379";
|
||||
|
||||
logger.log(`Connecting to Valkey at ${valkeyUrl}`);
|
||||
|
||||
const client = new Redis(valkeyUrl, {
|
||||
maxRetriesPerRequest: 3,
|
||||
retryStrategy: (times) => {
|
||||
const delay = Math.min(times * 50, 2000);
|
||||
logger.warn(
|
||||
`Valkey connection retry attempt ${times.toString()}, waiting ${delay.toString()}ms`
|
||||
);
|
||||
return delay;
|
||||
},
|
||||
reconnectOnError: (err) => {
|
||||
logger.error("Valkey connection error:", err.message);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
client.on("connect", () => {
|
||||
logger.log("Connected to Valkey");
|
||||
});
|
||||
|
||||
client.on("error", (err) => {
|
||||
logger.error("Valkey error:", err.message);
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redis Client Provider
|
||||
*
|
||||
* Provides a singleton Redis client instance for dependency injection.
|
||||
*/
|
||||
export const RedisProvider: Provider = {
|
||||
provide: "REDIS_CLIENT",
|
||||
useFactory: createRedisClient,
|
||||
};
|
||||
Reference in New Issue
Block a user