Skip to content

[SECURITY FEATURE]: Database-Backed User Authentication with Argon2id (replace BASIC auth) #544

@crivetimihai

Description

@crivetimihai

Security Feature: Database-Backed User Authentication with Argon2id

Summary

Replace the current HTTP Basic Authentication system that stores plaintext passwords in environment variables with a secure, database-backed user authentication system using Argon2id password hashing.

Current State

  • Authentication Method: HTTP Basic Auth
  • Password Storage: Plaintext in environment variables (BASIC_AUTH_USER, BASIC_AUTH_PASSWORD)
  • Security Risk: Medium- passwords exposed in environment, process listings, and configuration files
  • User Management: Single hardcoded admin user only

Proposed Solution

Implement a proper user authentication system with:

  • Database-backed user accounts
  • Argon2id password hashing (winner of the Password Hashing Competition)
  • Support for multiple users with role-based access
  • Secure password storage that never exposes plaintext passwords

Dependencies / Related Features

Direct Dependencies (Must be completed before or with this feature):

Related Security Features (Should be coordinated):

Authentication/Authorization Features (Natural progression):

Infrastructure Dependencies:

Testing & Validation:

Technical Requirements

1. Database Schema

Create new database tables for user management:

CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username VARCHAR(255) UNIQUE NOT NULL,
    email VARCHAR(255) UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    is_admin BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    last_login TIMESTAMP,
    failed_login_attempts INTEGER DEFAULT 0,
    locked_until TIMESTAMP
);

CREATE TABLE user_sessions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    session_token VARCHAR(255) UNIQUE NOT NULL,
    expires_at TIMESTAMP NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_sessions_token ON user_sessions(session_token);
CREATE INDEX idx_sessions_expires ON user_sessions(expires_at);

2. Password Hashing Implementation

Use Argon2id with secure parameters:

  • Memory Cost: 64 MB (minimum per OWASP)
  • Time Cost: 3 iterations (minimum per OWASP)
  • Parallelism: 1 thread
  • Salt Length: 16 bytes (generated per password)
  • Hash Length: 32 bytes

3. Authentication Flow

1. User submits username/password to /auth/login
2. System queries database for user by username
3. If user exists and is active:
   - Verify password against stored Argon2id hash
   - On success: Generate session token, update last_login
   - On failure: Increment failed_login_attempts
4. Return JWT token or session cookie for authenticated requests

4. API Endpoints

New authentication endpoints:

  • POST /auth/login - Authenticate user
  • POST /auth/logout - Invalidate session
  • POST /auth/refresh - Refresh JWT token
  • GET /auth/me - Get current user info

Admin user management endpoints:

  • GET /admin/users - List all users (admin only)
  • POST /admin/users - Create new user (admin only)
  • PUT /admin/users/{id} - Update user (admin only)
  • DELETE /admin/users/{id} - Deactivate user (admin only)
  • POST /admin/users/{id}/reset-password - Reset user password (admin only)

5. Security Features

  • Account Lockout: Lock account after 5 failed attempts for 15 minutes
  • Password Requirements: Minimum 12 characters, complexity optional but recommended
  • Session Management: Configurable session timeout, secure session tokens
  • Rate Limiting: Limit login attempts to 5 per minute per IP
  • Audit Logging: Log all authentication events (login, logout, failed attempts)

6. Configuration Changes

Replace current environment variables:

# OLD - REMOVE THESE
# BASIC_AUTH_USER=admin
# BASIC_AUTH_PASSWORD=changeme

# NEW
AUTH_SYSTEM=database  # Options: database, basic (for backwards compat)
SESSION_TIMEOUT=3600  # 1 hour
MAX_LOGIN_ATTEMPTS=5
LOCKOUT_DURATION=900  # 15 minutes
PASSWORD_MIN_LENGTH=12

7. Migration Process

  1. Create database tables
  2. Create initial admin user with temporary password
  3. On first login, force password change
  4. Provide CLI command for user management:
    python -m mcpgateway.auth create-user --username admin --email [email protected] --admin
    python -m mcpgateway.auth reset-password --username admin
    python -m mcpgateway.auth list-users

Benefits

  • Eliminates plaintext passwords in configuration
  • Supports multiple users with different access levels
  • Industry-standard security with Argon2id
  • Audit trail for all authentication events
  • Account lockout prevents brute force attacks
  • Scalable user management system

Dependencies

  • argon2-cffi >= 25.1.0 (Python Argon2 binding)
  • Existing SQLAlchemy setup
  • Existing JWT implementation (reuse for tokens)

Backwards Compatibility

  • Keep AUTH_SYSTEM=basic option for gradual migration
  • If AUTH_SYSTEM=basic, fall back to current behavior
  • Deprecation warning when using basic auth
  • Remove basic auth support in next major version

Success Criteria

  • No plaintext passwords in environment or configuration
  • All passwords hashed with Argon2id before storage
  • Support for multiple user accounts
  • Account lockout after failed attempts
  • Audit log of authentication events
  • CLI tools for user management
  • Comprehensive test coverage
  • Security documentation updated

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpythonPython / backend development (FastAPI)securityImproves securitytriageIssues / Features awaiting triage

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions