The OTP is stored in Redis as plain text and can be viewed using:
- Redis CLI (Command Line)
- Redis Desktop Manager (GUI)
- RedisInsight (Official GUI)
- Redis Commander (Web UI)
File: services/otpService.js
static async storeOTP(email, otp, expiryMinutes = 10) {
const redis = getRedisClient();
const key = `otp:${email.toLowerCase()}`;
await redis.setex(key, expiryMinutes * 60, otp);
console.log(`[OTP] Stored for ${email}, expires in ${expiryMinutes} minutes`);
}Key Format: otp:[email protected]
Value: 123456 (plain text, 6 digits)
TTL: 600 seconds (10 minutes)
static async getOTP(email) {
const redis = getRedisClient();
const key = `otp:${email.toLowerCase()}`;
return await redis.get(key);
}static async verifyOTP(email, otp) {
const storedOTP = await this.getOTP(email);
return storedOTP === otp; // Simple string comparison
}Verification: ✅ Code is correct and will work!
docker exec -it intervai-redis redis-cli> AUTH your-redis-password
OK# Get specific OTP
> GET otp:[email protected]
"123456"
# View all OTP keys
> KEYS otp:*
1) "otp:[email protected]"
2) "otp:[email protected]"
# Check TTL (time remaining)
> TTL otp:[email protected]
589
# Get all info at once
> GET otp:[email protected]
"123456"
> TTL otp:[email protected]
585# Check OTP request attempts
> GET otp:attempts:[email protected]
"2"
# Check verification attempts
> GET otp:verify:[email protected]
"1"
# View all tracking keys
> KEYS otp:attempts:*
> KEYS otp:verify:*> exitWindows/Mac/Linux:
# Download from: https://resp.app/
# Or use: https://github.com/qishibo/AnotherRedisDesktopManager- Open Redis Desktop Manager
- Click "Connect to Redis Server"
- Enter connection details:
- Name: IntervAI Redis
- Host: localhost
- Port: 6379
- Auth: your-redis-password
- Click "Test Connection"
- Click "OK"
- Expand connection
- Select database (usually db0)
- Search for:
otp:* - Click on key to view value
- See TTL in the interface
Screenshot Example:
Key: otp:[email protected]
Type: string
Value: 123456
TTL: 589 seconds
# Download from: https://redis.com/redis-enterprise/redis-insight/
# Or using Docker:
docker run -d --name redisinsight \
-p 8001:8001 \
redislabs/redisinsight:latestOpen browser: http://localhost:8001
- Click "Add Redis Database"
- Enter details:
- Host: host.docker.internal (or localhost)
- Port: 6379
- Password: your-redis-password
- Click "Add Database"
- Click on your database
- Go to "Browser" tab
- Search:
otp:* - Click on key to view:
- Value:
123456 - TTL:
589 seconds - Type:
string
- Value:
# Using Docker
docker run -d \
--name redis-commander \
-p 8081:8081 \
-e REDIS_HOSTS=local:redis:6379:0:your-password \
--network intervai_default \
rediscommander/redis-commander:latestOpen browser: http://localhost:8081
- Select database (db0)
- Search:
otp:* - Click on key
- View value and TTL
curl -X POST http://localhost:8000/api/v1/user/forgot-password \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'Response:
{
"success": true,
"message": "If the email exists, an OTP has been sent",
"data": {
"expiresIn": "10 minutes"
}
}docker-compose logs -f api | grep OTPOutput:
[OTP] Stored for [email protected], expires in 10 minutes
[Email] OTP sent to [email protected], MessageID: <...>
docker exec -it intervai-redis redis-cli
# Authenticate
> AUTH your-password
OK
# Get OTP
> GET otp:[email protected]
"123456"
# Check TTL
> TTL otp:[email protected]
589
# Check attempts
> GET otp:attempts:[email protected]
"1"curl -X POST http://localhost:8000/api/v1/user/verify-otp \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","otp":"123456"}'Response:
{
"success": true,
"message": "OTP verified successfully",
"data": {
"expiresIn": "9 minutes"
}
}> GET otp:[email protected]
"123456" # Still there until password reset
> GET otp:verify:[email protected]
"1" # Verification attempt trackedcurl -X POST http://localhost:8000/api/v1/user/reset-password \
-H "Content-Type: application/json" \
-d '{
"email":"[email protected]",
"otp":"123456",
"newPassword":"NewPass123!"
}'Response:
{
"success": true,
"message": "Password reset successfully. You can now login with your new password"
}> GET otp:[email protected]
(nil) # OTP deleted after successful reset
> KEYS otp:*
(empty list or set)Key Pattern: otp:{email}
Example: otp:[email protected]
Value: "123456"
Type: string
TTL: 600 seconds (10 minutes)
Key Pattern: otp:attempts:{email}
Example: otp:attempts:[email protected]
Value: "2"
Type: string
TTL: 3600 seconds (1 hour)
Key Pattern: otp:verify:{email}
Example: otp:verify:[email protected]
Value: "1"
Type: string
TTL: 600 seconds (10 minutes)
# All OTP codes
KEYS otp:*
# All rate limit tracking
KEYS otp:attempts:*
# All verification tracking
KEYS otp:verify:*
# Everything OTP-related
KEYS otp*# Get OTP and TTL
MGET otp:[email protected]
TTL otp:[email protected]
# Get all info for an email
GET otp:[email protected]
GET otp:attempts:[email protected]
GET otp:verify:[email protected]# Watch all Redis commands in real-time
MONITOR
# Then in another terminal, request OTP
# You'll see: SETEX otp:[email protected] 600 "123456"# Check if key exists
EXISTS otp:[email protected]
# Get key type
TYPE otp:[email protected]
# Get TTL in milliseconds
PTTL otp:[email protected]
# Get all keys count
DBSIZECheck 1: Is OTP actually stored?
docker-compose logs -f api | grep "OTP] Stored"Check 2: Redis connection working?
docker exec -it intervai-redis redis-cli
> PING
PONGCheck 3: Correct database?
> SELECT 0
OK
> KEYS otp:*Check 4: OTP expired?
> TTL otp:[email protected]
-2 # Key doesn't exist or expiredError: (error) NOAUTH Authentication required.
Fix:
> AUTH your-redis-password
OKCheck current database:
> INFO keyspace
# Keyspace
db0:keys=5,expires=5,avg_ttl=589000Switch database:
> SELECT 0
OK$ docker exec -it intervai-redis redis-cli
127.0.0.1:6379> AUTH mypassword
OK
127.0.0.1:6379> GET otp:[email protected]
"123456"
127.0.0.1:6379> TTL otp:[email protected]
(integer) 589
127.0.0.1:6379> GET otp:attempts:[email protected]
"1"
127.0.0.1:6379> KEYS otp:*
1) "otp:[email protected]"
2) "otp:attempts:[email protected]"
127.0.0.1:6379> exit┌─────────────────────────────────────────┐
│ Browser │
├─────────────────────────────────────────┤
│ Search: otp:* [🔍] │
├─────────────────────────────────────────┤
│ ✓ otp:[email protected] │
│ Type: string │
│ Value: 123456 │
│ TTL: 589 seconds │
│ │
│ ✓ otp:attempts:[email protected] │
│ Type: string │
│ Value: 1 │
│ TTL: 3589 seconds │
└─────────────────────────────────────────┘
- OTP stored as plain text string
- Key format:
otp:{email} - TTL set to 600 seconds (10 minutes)
- Email normalized to lowercase
- Console logging enabled
- Error handling in place
- Can connect to Redis CLI
- Can authenticate with password
- Can see OTP keys with
KEYS otp:* - Can get OTP value with
GET otp:email - Can see TTL with
TTL otp:email - Can see rate limiting with
GET otp:attempts:email
- Request OTP returns success
- Email received with OTP
- OTP visible in Redis
- OTP verification works
- Password reset works
- OTP deleted after reset
YES, you can absolutely see the OTP in Redis!
The OTP is stored as:
- Plain text (not encrypted)
- String type (not hash or list)
- Key format:
otp:[email protected] - Value:
123456(6 digits) - TTL: 600 seconds (10 minutes)
Best way to view:
- Quick check: Redis CLI (
docker exec -it intervai-redis redis-cli) - Visual: RedisInsight (official GUI)
- Web-based: Redis Commander
The code is correct and will work perfectly! ✅
Need help? Check the troubleshooting section or run the complete testing flow above!