Skip to main content

Authentication

Overview

The application implements a comprehensive role-based access control (RBAC) system with three user roles: Admin, Coach, and Runner.

Authentication System

Architecture:

  • Provider-based: Extensible authentication provider architecture
  • Local Authentication: Bcrypt password hashing (cost factor 12)
  • Session Management: Flask-Login for session handling
  • Rate Limiting: 50 login attempts per 15 minutes (configurable)

Components:

  • app/auth/providers/ - Authentication provider implementations
  • app/auth/user.py - User model with Flask-Login integration
  • app/auth/routes.py - Login/logout/profile endpoints
  • app/auth/permissions.py - Authorization decorators

User Roles & Permissions

RoleAthletes DashboardAdmin DashboardRunner AccessCreate AthletesUser Management
AdminFull access, all runnersFull accessAll runnersYesFull CRUD
CoachFull access, assigned runnersLimited (Workouts & Schemas only)Assigned runners onlyYesCannot manage users
RunnerAuto-navigated to own viewNo accessOwn profile onlyNoProfile edit only

Multi-role Users: Users with multiple roles (e.g., Coach + Runner) receive the highest level of access. A Coach who is also a Runner will have Coach-level access to the Athletes Dashboard.

Runner Auto-Navigation: Pure runner users (those with only the runner role) are automatically redirected to their personal training view (/#/runner/{id}/info/) upon login, bypassing the Athletes Dashboard entirely. They cannot navigate back to the dashboard and do not see the "Add New Athlete" card.

User-Runner Integration

Data Model:

// Users Collection
{
_id: ObjectId,
username: String (unique),
email: String (unique),
password_hash: String (bcrypt),
roles: [String], // ["admin", "coach", "runner"]
runner_id: ObjectId, // Links to runner profile (if runner role)
coached_runners: [ObjectId], // Array of runner IDs (if coach role)
is_active: Boolean,
created_at: DateTime,
last_login: DateTime
}

// Runner Collection
{
_id: ObjectId,
runnerID: String, // Legacy string ID
name: String,
email: String,
profile_complete: Boolean, // Flags incomplete profiles for onboarding
// ... training data fields ...
}

Relationship: One-way link from users.runner_idrunner._id

Onboarding Workflow

New runner users go through a 4-step onboarding wizard:

  1. Basic Info: Name, age
  2. Heart Rate Zones: 5 HR zones with automatic calculation
  3. Personal Bests: Multiple distances with performance metric calculation
  4. Training Parameters: Physiological model parameters

Implementation:

  • First login detects profile_complete: false and redirects to /onboarding
  • Onboarding form matches "Add New Athlete" wizard format
  • After completion, redirects to runner detail page via hash route /#/runner/{id}/info/

User Creation Workflows

Workflow 1: Admin creates runner user

Admin → User Management → Create User (runner role)

User account created

Runner profile auto-created with profile_complete: false

Runner logs in → Redirected to onboarding

Workflow 2: Coach creates athlete

Coach → Add New Athlete → Complete 4-step wizard

Runner profile created

Optional: Create user account (Step 5)

If yes: User account created and linked

Coach auto-assigned to runner

Workflow 3: Migration of existing data

Migration script → Analyze orphaned users/runners

Auto-create missing runner profiles or user accounts

Link by email matching

Flag incomplete profiles for onboarding

Route Protection

Decorators:

  • @login_required - Requires authenticated user
  • @admin_only - Admin role required
  • @coach_or_admin - Coach or Admin role required
  • @role_required('role_name') - Custom role requirement

Permission Filtering:

  • /runners endpoint returns filtered results based on role
  • Runners only see their own profile
  • Coaches only see assigned runners
  • Admins see all runners

Security Implementation

  1. Password Security

    • Bcrypt hashing with cost factor 12
    • Password strength validation (8+ chars, uppercase, lowercase, digit, special)
    • Password change requires current password verification
    • Last admin protection (cannot remove admin role from last admin user)
  2. Session Security

    • Flask-Login session management
    • Secure session cookies
    • Rate limiting on login endpoint
  3. Input Validation

    • Username validation (3-30 chars, alphanumeric + underscore)
    • Email validation
    • Role validation against allowed roles
  4. API Security

    • All routes require authentication
    • Role-based authorization on sensitive endpoints
    • 401/403 error pages for unauthorized access
  5. Data Protection

    • MongoDB connections via SSL/TLS
    • Environment variables for sensitive configuration
    • Certificate management via certifi package