277 lines
7.3 KiB
Markdown
277 lines
7.3 KiB
Markdown
# 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
|
|
|
|
```cpp
|
|
LOGIN:username:password
|
|
```
|
|
|
|
Server extracts username and password from the message format.
|
|
|
|
### 2. Database Lookup
|
|
|
|
```cpp
|
|
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
|
|
|
|
```cpp
|
|
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
|
|
|
|
```cpp
|
|
// 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
|
|
|
|
```cpp
|
|
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
|
|
|
|
```java
|
|
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
|
|
|
|
```java
|
|
@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
|
|
|
|
```java
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
./dbmanager list
|
|
```
|
|
|
|
### Test Authentication
|
|
|
|
```bash
|
|
./dbmanager authenticate alice AlicePassword789
|
|
```
|
|
|
|
## Running the System
|
|
|
|
### 1. Setup Database
|
|
|
|
```bash
|
|
cd build
|
|
./dbmanager register alice AlicePassword789 alice@scar.local user
|
|
./dbmanager register bob BobPassword000 bob@scar.local user
|
|
```
|
|
|
|
### 2. Start Server
|
|
|
|
```bash
|
|
./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
|