# BuyerKiosk Authentication Flow Documentation

This document provides a comprehensive trace of the authentication and session management flow in the BuyerKiosk web application.

## Table of Contents
1. [Login Routes](#login-routes)
2. [Session Initialization](#session-initialization)
3. [Login Process](#login-process)
4. [Password Verification](#password-verification)
5. [Session Creation](#session-creation)
6. [Cookie Management](#cookie-management)
7. [Remember Me Functionality](#remember-me-functionality)
8. [Logout Process](#logout-process)
9. [API Authentication](#api-authentication)

## Login Routes

### GET /login Route
**File**: `public_html/index.php:59-62`
```php
$app->get('/login/?', function() use ($app) {
    $controller = new UF\AccountController($app);
    $controller->pageLogin();
});
```

### POST /account/login Route
**File**: `public_html/index.php:2665-2669`
```php
$app->post('/account/:action/?', function ($action) use ($app) {
    $controller = new UF\AccountController($app);
    switch ($action) {
        case "login": return $controller->login();
        // ... other actions
    }
});
```

### Login Form Submission
**File**: `userfrosting/templates/common/login.html:56`
```html
<form name="login" method="post" action="/account/login" class="form-horizontal">
```

## Session Initialization

### UserSession Middleware
**File**: `userfrosting/middleware/UserSession.php`
**Purpose**: Handles session setup before each request

1. **Hook Registration** (line 16):
   ```php
   $this->app->hook('slim.before', array($this, 'setup'));
   ```

2. **Session Setup Process** (lines 20-84):
   - Initializes RememberMe authenticator with PDO storage
   - Starts PHP session: `session_start();`
   - Checks if user already exists in session
   - Validates RememberMe cookie if present
   - Creates guest user if no authentication found

3. **Existing Session Check** (lines 32-44):
   ```php
   if(isset($_SESSION["userfrosting"]["user"]) && is_object($_SESSION["userfrosting"]["user"])) {
       // Validate RememberMe cookie
       if(!empty($_COOKIE[$this->app->remember_me->getCookieName()]) && !$this->app->remember_me->cookieIsValid()) {
           // Logout if cookie invalid
       }
       // Refresh user data
       $_SESSION["userfrosting"]["user"] = $_SESSION["userfrosting"]["user"]->fresh();
   }
   ```

## Login Process

### AccountController::login() Method
**File**: `userfrosting/controllers/AccountController.php:205-331`

1. **Request Validation** (lines 207-237):
   - Loads login form schema
   - Validates POST data using Fortress
   - Sanitizes input data

2. **User Lookup** (lines 239-265):
   - Determines if login is email or username
   - Fetches user from database:
     ```php
     $user = UserLoader::fetch($data['user_name'], 'email'); // Email login
     $user = UserLoader::fetch($data['user_name'], 'user_name'); // Username login
     ```

3. **Account Status Checks** (lines 268-280):
   - Verifies account is enabled (`$user->enabled == 1`)
   - Verifies account is activated (`$user->active == 1`)

4. **Password Verification** (line 283):
   ```php
   if ($user->verifyPassword($data['password'])) {
       // Login successful
   }
   ```

## Password Verification

### MySqlUser::verifyPassword() Method
**File**: `userfrosting/models/mysql/MySqlUser.php:357-380`

Supports three password hash types:

1. **SHA1 (Legacy)** (lines 358-365):
   ```php
   if (Authentication::getPasswordHashType($this->password) == "sha1"){
       $salt = substr($this->password, 0, 25);
       $hash_input = $salt . sha1($salt . $password);
       return ($hash_input == $this->password);
   }
   ```

2. **Homegrown BCrypt** (lines 368-375):
   ```php
   else if (Authentication::getPasswordHashType($this->password) == "homegrown"){
       $cost = '12';
       return (substr($this->password, 0, 60) == crypt($password, "$2y$".$cost."$".substr($this->password, 60)));
   }
   ```

3. **Modern (PHP password_hash)** (lines 377-379):
   ```php
   else {
       return password_verify($password, $this->password);
   }
   ```

### Password Compatibility Library
**File**: `userfrosting/auth/password.php`
- Provides PHP 5.5+ password hashing API compatibility
- Implements `password_hash()`, `password_verify()`, etc.
- Uses BCrypt with cost factor 10 by default

## Session Creation

### After Successful Password Verification
**File**: `userfrosting/controllers/AccountController.php:284-323`

1. **User Login Method** (line 284):
   ```php
   $user->login();
   ```
   - Updates `last_sign_in_stamp` in database
   - Upgrades legacy password hashes to modern format

2. **Session Regeneration** (line 285):
   ```php
   session_regenerate_id();
   ```

3. **Session Storage** (lines 293-294):
   ```php
   $_SESSION["userfrosting"]["user"] = $user;
   $this->_app->user = $_SESSION["userfrosting"]["user"];
   ```

## Cookie Management

### Remember Me Cookie
**File**: `userfrosting/controllers/AccountController.php:287-291`
```php
if(!empty($data['rememberme'])) {
    $this->_app->remember_me->createCookie($user->id);
} else {
    $this->_app->remember_me->clearCookie();
}
```

### JWT Cookie ("pineapple")
**File**: `userfrosting/controllers/AccountController.php:296-322`
```php
// Create JWT token
$data = [
    'iat'  => $issuedAt,
    'jti'  => $tokenId,
    'iss'  => $serverName,
    'nbf'  => $notBefore,
    'exp'  => $expire,
    'data' => ['userName' => $data['user_name']]
];
$jwt = \JWT::encode($data, $secretKey, 'HS256');
setcookie("pineapple", base64_encode($jwt), time()+259200, '/');
```
- Cookie expires in 3 days (259200 seconds)
- Contains encoded JWT with user information

### Session Configuration
**File**: `userfrosting/config-userfrosting.php:18-22`
```php
ini_set('session.gc_maxlifetime', 60*60*24); // 24 hours
session_cache_limiter(false);
session_name("UserFrosting");
```

## Remember Me Functionality

### Database Schema
**File**: `userfrosting/initialize.php:213-219`
```php
$app->remember_me_table = [
    'tableName' => $app->config('db')['db_prefix'] . "user_rememberme",
    'credentialColumn' => 'user_id',
    'tokenColumn' => 'token',
    'persistentTokenColumn' => 'persistent_token',
    'expiresColumn' => 'expires'
];
```

### Auto-Login via RememberMe
**File**: `userfrosting/middleware/UserSession.php:46-68`
```php
$user_id = $this->app->remember_me->login();
if($user_id) {
    $_SESSION["userfrosting"]["user"] = \UserFrosting\UserLoader::fetch($user_id);
    $_SESSION['remembered_by_cookie'] = true;
}
```

## Logout Process

### AccountController::logout() Method
**File**: `userfrosting/controllers/AccountController.php:333-345`

1. **Complete Logout** (removes all RememberMe tokens):
   ```php
   if ($complete){
       $storage->cleanAllTriplets($this->_app->user->id);
   }
   ```

2. **Standard Logout**:
   ```php
   $this->_app->remember_me->clearCookie($this->_app->user->id);
   session_regenerate_id(true);
   session_destroy();
   $this->_app->deleteCookie('UserFrosting');
   $this->_app->redirect("/");
   ```

## API Authentication

### Endpoint: POST /api/authenticate-user
**File**: `userfrosting/routes/api.php:59-121`

Used for API-based authentication (e.g., mobile apps, external services):

1. **Required Parameters**:
   - `username`
   - `password`
   - `access_level`
   - `typeNum` (store identifier)

2. **Verification Steps**:
   - HTTPS requirement check
   - User lookup by username
   - Password verification using `password_verify()`
   - Store authorization check
   - Access level verification

3. **Response Format**:
   ```json
   {
       "userId": 123,
       "name": "Display Name",
       "error": "success" // or error message
   }
   ```

### API Key Authentication
**File**: `userfrosting/models/mysql/MySqlUser.php:381-395`

Alternative authentication method using API keys:
```php
public function verifyAPIKey($apiKey, \Klogger $log){
    // Queries uf_apiKey_user and uf_apiKey tables
    // Verifies key matches and is active
}
```

## Security Features

1. **CSRF Protection**:
   - Token generation: `\NoCSRF::generate($csrf_key)`
   - Currently disabled in login method (line 217-221)

2. **Password Security**:
   - Supports multiple hash types for backward compatibility
   - Automatically upgrades legacy hashes to modern bcrypt
   - Uses PHP's native `password_verify()` for modern hashes

3. **Session Security**:
   - Session ID regeneration on login/logout
   - 24-hour session lifetime
   - RememberMe token validation

4. **HTTPS Enforcement**:
   - API authentication requires HTTPS
   - Checked via `isHTTPS($app)` function

## Debugging Tips

1. **Error Logging**: The system uses extensive error_log() calls:
   - "authenticate-user" - API authentication start/end
   - "Username Not Found" - User lookup failures
   - "Password Not Verified" - Failed password checks
   - "Cookie was stolen!" - Invalid RememberMe tokens

2. **Session Storage**:
   - User object stored in `$_SESSION["userfrosting"]["user"]`
   - Also accessible via `$app->user`

3. **Common Issues**:
   - Empty SQL queries are logged (see DebugPDO class in initialize.php)
   - Deprecated warnings suppressed for PHP 8.4 compatibility
   - Password hash upgrades logged as notices

## Store-Specific Authentication

The system supports multi-store architecture with store-specific access:
- User groups follow pattern: `[a-z][a-z]\d+` (e.g., "ou00", "pa11631")
- Store authorization checked via `$user->checkStoreGroup($typeNum)`
- Each store can have its own user permissions