scar-chat/AUTHENTICATION.md

7.3 KiB

SCAR Chat - Authentication & Nickname System

Overview

The SCAR Chat system now includes user authentication with database-backed nicknames. Each client must login with valid credentials before they can send messages or perform actions.

Authentication Flow

Server-Side

  1. Client connects via SSL/TLS
  2. Server waits for LOGIN message: LOGIN:username:password
  3. Server validates credentials against SQLite database
  4. If valid: Server sends LOGIN_SUCCESS:username and accepts messages from this client
  5. If invalid: Server sends LOGIN_FAILED:reason and blocks messages
  6. All messages must come from authenticated clients - unauthenticated clients are rejected with ERROR:Not authenticated

Client-Side (Android)

  1. User enters server hostname and port
  2. Click "Connect" to establish SSL connection
  3. After connecting, username/password fields become enabled
  4. User enters credentials and clicks "Login"
  5. On successful login, credentials fields are disabled and user can send messages
  6. All sent messages show the authenticated username in the format: *{HH:MM:SS}* username: message

Message Format

All messages now include timestamp and authenticated username:

*{HH:MM:SS}* username: message content

Examples:

  • *{14:32:45}* alice: Hello everyone!
  • *{14:32:52}* admin: System message
  • *{14:33:01}* bob: Nice to meet you

Server Authentication Flow

1. Parse LOGIN Message

LOGIN:username:password

Server extracts username and password from the message format.

2. Database Lookup

if (global_db->authenticate_user(username, password)) {
    // Authentication successful
    nickname = username;
    authenticated = true;
    client_nicknames[ssl] = username;
}

The database validates the credentials by:

  • Checking if user exists
  • Checking if user account is active
  • Computing SHA256(password + salt) and comparing with stored hash

3. Track Authenticated Client

std::map<SSL*, std::string> client_nicknames;  // Track authenticated clients
std::mutex nicknames_mutex;

The server maintains a map of SSL connections to usernames to ensure:

  • Only authenticated clients can send messages
  • Camera events are attributed to correct user
  • Disconnects are properly logged

4. Accept/Reject Messages

Authenticated clients:

  • Messages are accepted and broadcast with nickname
  • Format: *{timestamp}* nickname: message
  • CAMERA_ENABLE/DISABLE events also use nickname

Unauthenticated clients:

  • Messages are rejected
  • Response: ERROR:Not authenticated. Send LOGIN:username:password
  • Client must send LOGIN message first

Server API

Initialize with Database

// In main()
global_db = new Database("scar_chat.db");
if (!global_db->initialize()) {
    std::cerr << "Failed to initialize database" << std::endl;
    return 1;
}

Per-Client Handler

void handle_client(SSL *ssl, int client_socket) {
    std::string nickname;
    bool authenticated = false;
    
    // Wait for LOGIN message
    // Validate against database
    // If valid, set authenticated = true and nickname = username
    
    // Reject all messages from unauthenticated clients
    if (!authenticated) {
        SSL_write(ssl, error_msg);
        continue;
    }
    
    // Process authenticated messages
}

Android Client Flow

UI Components Added

  • Username Input: Text field (disabled until connected)
  • Password Input: Password field (disabled until connected)
  • Login Button: Sends LOGIN:username:password (disabled until connected)
  • Connection Status: Shows current connection and login state

Login Handling

private void attemptLogin() {
    String username = usernameInput.getText().toString().trim();
    String password = passwordInput.getText().toString().trim();
    
    String loginCmd = "LOGIN:" + username + ":" + password;
    chatConnection.sendMessage(loginCmd);
}

Response Handling

@Override
public void onMessageReceived(String message) {
    if (message.startsWith("LOGIN_SUCCESS:")) {
        // Extract username
        currentUsername = message.substring("LOGIN_SUCCESS:".length()).trim();
        // Enable chat
        connectionStatus.setText("Logged in as: " + currentUsername);
        loginBtn.setEnabled(false);
    } else if (message.startsWith("LOGIN_FAILED:")) {
        // Show error
        String reason = message.substring("LOGIN_FAILED:".length()).trim();
        Toast.makeText(this, "Login failed: " + reason, Toast.LENGTH_SHORT).show();
    }
}

Send Messages with Nickname

private void sendMessage() {
    if (mainActivity.getCurrentUsername().isEmpty()) {
        Toast.makeText(getContext(), "Please login first", Toast.LENGTH_SHORT).show();
        return;
    }
    
    String username = mainActivity.getCurrentUsername();
    String timestamp = new SimpleDateFormat("HH:mm:ss").format(new Date());
    String formattedMsg = "*{" + timestamp + "}* " + username + ": " + message;
}

Database User Management

Create Users for Testing

cd build
./dbmanager register alice AlicePassword789 alice@scar.local user
./dbmanager register bob BobPassword000 bob@scar.local user
./dbmanager register admin AdminPass123 admin@scar.local admin

Verify Users

./dbmanager list

Test Authentication

./dbmanager authenticate alice AlicePassword789

Running the System

1. Setup Database

cd build
./dbmanager register alice AlicePassword789 alice@scar.local user
./dbmanager register bob BobPassword000 bob@scar.local user

2. Start Server

./chat_server ../certs/server.crt ../certs/server.key

Server output:

Database initialized successfully
SCAR Chat Server listening on port 42317

3. Connect Android Client

  1. Open SCAR Chat app
  2. Enter server hostname (e.g., "192.168.1.100")
  3. Enter port (42317)
  4. Click "Connect"
  5. Username/Password fields become enabled
  6. Enter credentials: alice / AlicePassword789
  7. Click "Login"
  8. Send messages - they will appear with nickname "alice"

4. Verify Server Logs

User authenticated: alice (FD: 4)
User authenticated: bob (FD: 5)
Received: *{14:32:45}* alice: Hello Bob!

Security Considerations

  1. Passwords are NOT transmitted in plain text - TLS/SSL encrypts all traffic
  2. Passwords are stored securely - SHA256 with unique salt per user
  3. Each connection is independent - disconnecting doesn't affect other users
  4. Unauthenticated clients are isolated - cannot access chat or perform actions

Error Handling

Server-Side Errors

Message Meaning
LOGIN_FAILED:Invalid credentials Username not found or password incorrect
ERROR:Not authenticated Client tried to send message without logging in
ERROR:Account inactive User account has been deactivated

Client-Side Errors

Error Resolution
"Not connected to server" Click Connect first
"Login failed: Invalid credentials" Check username/password spelling
"Please login first" User must complete login before sending messages

Future Enhancements

  • Session tokens with expiration
  • Multiple devices per user
  • Rate limiting per user
  • Activity logging
  • User profile information
  • Message history per user
  • Direct messaging between users