# Login System Documentation ## Overview A complete authentication system for the CGW Product Finder that integrates with the user management system. Users must log in with their credentials to access the product finder application. ## Features ### 🔐 Secure Authentication - Password verification using PBKDF2-SHA256 hashing - Session-based authentication with HTTP-only cookies - Automatic session management - Active/inactive user account checking ### 📍 Multi-Location Support - Automatic location selection for single-location users - Location selection page for users with multiple accessible locations - Default location preference - Location-based access control ### 🛡️ Security Features - Login required decorator protects all main routes - Inactive accounts are automatically blocked - Sessions expire on logout or server restart - Secure session cookies (HTTP-only, SameSite) ## User Flow ### 1. Login Process 1. User visits the app → Redirected to `/login` 2. User enters **username** and **password** 3. System validates credentials against `users.json` 4. System checks if user account is **active** 5. If valid and active: - Session is created - User accessible locations are loaded ### 2. Location Selection (if applicable) - **Single Accessible Location**: User goes directly to main app (location selection bypassed) - **Multiple Accessible Locations**: User is redirected to `/select-location` - Shows all accessible locations - Default location is pre-selected - User can choose their working location - Selection is saved to session - **Note**: Default location is automatically marked as accessible when user is created ### 3. Main Application Access - User accesses the Product Finder - User info displayed in header (username + current location) - Logout button available in header ## Routes ### Public Routes (No Login Required) - `GET /login` - Login page - `POST /api/login` - Login endpoint - `GET /users` - User management page ### Protected Routes (Login Required) - `GET /` - Main product finder app - `GET /quiz` - Quiz page (alias for main app) - `GET /image-test` - Image generation test page - `GET /select-location` - Location selection page - `POST /api/select-location` - Set current location ### Session Routes - `GET /api/session` - Get current session info - `POST /api/logout` - Logout and clear session ## API Endpoints ### POST /api/login Authenticate user and create session. **Request:** ```json { "username": "john_doe", "password": "password123" } ``` **Success Response:** ```json { "status": "success", "message": "Login successful", "requiresLocationSelection": true } ``` **Error Responses:** ```json { "status": "error", "message": "Invalid username or password" } ``` ```json { "status": "error", "message": "Account is inactive. Please contact an administrator." } ``` ### GET /api/session Get current user session information. **Response:** ```json { "status": "success", "username": "john_doe", "defaultLocation": "LINDS", "currentLocation": "KC", "accessibleLocations": ["LINDS", "KC", "IOLA"] } ``` ### POST /api/select-location Select a location for the current session. **Request:** ```json { "location": "KC" } ``` **Response:** ```json { "status": "success", "message": "Location selected", "currentLocation": "KC" } ``` ### POST /api/logout Log out and clear session. **Response:** ```json { "status": "success", "message": "Logged out successfully" } ``` ## Session Data The session stores: - `user_id`: Index of user in users.json - `username`: Username string - `defaultLocation`: User's default location code - `currentLocation`: Currently selected location code - `accessibleLocations`: Array of location codes user can access ## Authentication Decorator The `@login_required` decorator protects routes: ```python @app.route('/protected-page') @login_required def protected_page(): return render_template('protected.html') ``` The decorator: 1. Checks if user is logged in (has `user_id` in session) 2. Validates user still exists in users.json 3. Checks if user account is still active 4. Redirects to login if any check fails ## Getting Current User in Routes ```python @app.route('/my-route') @login_required def my_route(): user = get_current_user() username = session.get('username') current_location = session.get('currentLocation') # Use user data... return render_template('page.html') ``` ## Location-Based Access Control Users can only access locations they have permission for: ```python # In users.json { "username": "john_doe", "locationSettings": { "LINDS": { "accessible": true }, "IOLA": { "accessible": false }, "KC": { "accessible": true }, "BMD": { "accessible": false } } } ``` This user can access: - ✅ Lindsborg (LINDS) - ✅ KC (KC) - ❌ Iola (IOLA) - ❌ BMD (BMD) ## User Interface Components ### Login Page (`/login`) - Clean, centered login form - Username and password fields - Submit button with loading spinner - Link to User Management page - Error message display ### Location Selection Page (`/select-location`) - Shows logged-in username - Shows default location - Radio buttons for each accessible location - Default location is pre-selected - Continue and Logout buttons ### Main App Header - User info display: `👤 username | 📍 location` - Logout button in header - Positioned in top-right corner ## Security Considerations ### Password Security - Passwords are hashed using PBKDF2-SHA256 - Hashes are never reversed or displayed - Hash verification happens server-side only ### Session Security - Sessions use secure random keys - Cookies are HTTP-only (not accessible via JavaScript) - SameSite cookie policy prevents CSRF attacks - Sessions cleared on logout ### Account Status - Inactive accounts cannot log in - If account is deactivated while logged in, next request will log them out - User must have at least one accessible location ## Testing the Login System ### Test User Creation 1. Go to `/users` 2. Create a test user: - Username: `testuser` - Password: `password123` - Default Location: Lindsborg - Check "Accessible" for Lindsborg and KC ### Test Login Flow 1. Go to `/` (should redirect to `/login`) 2. Enter credentials: `testuser` / `password123` 3. Click "Sign In" 4. Since user has 2 accessible locations → redirected to `/select-location` 5. Choose a location and click "Continue" 6. Now viewing main Product Finder app 7. See user info in header 8. Click "Logout" to end session ### Test Single Location User 1. Create user with only 1 accessible location 2. Log in 3. Should go directly to main app (skip location selection) ### Test Inactive User 1. Create and log in as a user 2. In User Management, toggle user to "Inactive" 3. Try to log in → Should see "Account is inactive" message ## Troubleshooting ### "Please log in first" on all pages - Session may have expired - Server may have restarted (sessions are in-memory) - Clear browser cookies and log in again ### "User not found" error - User may have been deleted while logged in - Log out and log back in ### Can't access certain locations - Check user's "Accessible" checkboxes in User Management - User must have at least one accessible location ### Stuck on location selection page - User must have multiple accessible locations - If this shouldn't happen, check user's location settings - Or click "Sign Out" and contact administrator ## Future Enhancements Potential additions: - [ ] Remember me checkbox (persistent sessions) - [ ] Password reset functionality - [ ] Session timeout after inactivity - [ ] Login attempt limiting (brute force protection) - [ ] Two-factor authentication - [ ] Session management dashboard - [ ] Location switching without re-login - [ ] Audit log of login attempts