Skip to content

Latest commit

 

History

History
181 lines (139 loc) · 5.16 KB

File metadata and controls

181 lines (139 loc) · 5.16 KB

Re-Authentication System Implementation

Feature Overview

Implemented a flexible authentication system that allows users to re-authenticate with any account code, even if their Telegram account is already linked to another user.

How It Works

Previous Behavior (Restrictive)

  • ❌ If Telegram ID was already linked to User A, trying to authenticate as User B would fail
  • ❌ Error: "This Telegram account is already linked to another user"
  • ❌ Users couldn't switch between accounts

New Behavior (Flexible)

  • ✅ If Telegram ID is linked to User A, authenticating as User B automatically unlinks from A
  • ✅ Seamlessly switches between accounts using authentication codes
  • ✅ Perfect for testing, development, and legitimate account switching

Implementation Details

What Happens During Re-Authentication

  1. User authenticates with a code (e.g., /auth USRO4IOTW)

  2. System checks for existing links:

    // Find if this Telegram ID is linked to another user
    const existingTelegramUser = await User.findOne({ 
        telegramId: telegramUser.id.toString(),
        _id: { $ne: user._id }
    });
  3. Automatic unlinking (if found):

    // Unlink from previous user
    existingTelegramUser.telegramId = null;
    existingTelegramUser.telegramUsername = null;
    existingTelegramUser.telegramLinked = false;
    await existingTelegramUser.save();
  4. Link to new user:

    // Link Telegram account to the new user
    user.telegramId = telegramUser.id.toString();
    user.telegramUsername = telegramUser.username;
    user.telegramLinked = true;
    await user.save();

Updated Functions

1. authenticateUser() - User Code Authentication

  • Unlinks Telegram from previous user if already linked
  • Links to new user with valid code
  • Logs all re-linking operations

2. authenticateAdmin() - Admin Code Authentication

  • Same unlinking logic for admin accounts
  • Allows switching between admin accounts

3. authenticateLegacyQuest() - Legacy Quest Codes

  • Compatible with older quest invitation codes
  • Also supports re-authentication

Console Logs

When re-authentication happens, you'll see:

⚠️ Telegram ID 845713188 is already linked to user: Subham Agaarwal
🔄 Unlinking Telegram from previous user to allow re-authentication...
✅ Telegram unlinked from Subham Agaarwal
✅ Attempting to save user with telegramId: 845713188
✅ User saved successfully!

Use Cases

1. Testing & Development

# Test as User A
/auth USRABC123

# Now test as User B (same Telegram account)
/auth USRDEF456  # Automatically unlinks from A, links to B

2. Account Switching

Users can legitimately switch between multiple TaskQuest accounts using their Telegram

3. Account Recovery

If someone gets the wrong account, they can re-authenticate with the correct code

Security Considerations

⚠️ Important Notes:

  1. Code Security: Anyone with a valid authentication code can link their Telegram to that account

    • Keep codes private
    • Codes should expire after use or time limit
    • Generate new codes from the admin dashboard
  2. Session Hijacking Prevention:

    • Previous user is automatically unlinked
    • They will need to re-authenticate to regain access
    • Consider adding notifications when accounts are unlinked
  3. Audit Trail: All re-authentications are logged in console

    • Monitor for suspicious activity
    • Can be extended to database logging

Best Practices

For Development/Testing:

✅ Use this feature freely to test different user roles

For Production:

  1. Add email notifications when Telegram is unlinked
  2. Implement rate limiting on authentication attempts
  3. Add confirmation step before unlinking (optional)
  4. Log to database for audit trail

Example Production Enhancement

// Before unlinking, notify the user
if (existingTelegramUser) {
    // Send notification to previous user
    await notifyUserOfUnlink(existingTelegramUser);
    
    // Log to database for audit
    await AuditLog.create({
        action: 'TELEGRAM_UNLINK',
        userId: existingTelegramUser._id,
        newUserId: user._id,
        telegramId: telegramUser.id,
        timestamp: new Date()
    });
    
    // Then unlink
    existingTelegramUser.telegramId = null;
    // ...
}

Files Modified

  • src/bot/commands/auth.js - All three authentication functions updated

Testing

Test Scenario 1: Switch Between Users

# Authenticate as User A
/auth USRABC123
# ✅ Success: Linked as User A

# Authenticate as User B (same Telegram)
/auth USRDEF456
# ✅ Success: Automatically switched to User B
# User A is now unlinked

# Verify User A is unlinked
# (User A can re-authenticate with their code to re-link)

Test Scenario 2: Admin to User Switch

# Authenticate as Admin
/auth ADMXYZ789
# ✅ Success: Linked as Admin

# Switch to regular user
/auth USRABC123
# ✅ Success: Now linked as regular user
# Admin account is unlinked

Status

Implemented and Working!

You can now authenticate with any valid code, and the system will automatically handle unlinking and relinking.