Feature: User Authentication
Relevant source files
The following files were used as context for generating this wiki page:The user authentication feature in the SPK Kajek application is a comprehensive system designed to secure access to the dashboard. It is built upon a JSON Web Token (JWT) based mechanism, integrating a React frontend with a FastAPI backend. The system manages user login, session persistence via localStorage, profile management (view and update), and secure password changes.
The authentication flow is initiated from the LoginView component, which communicates with the backend API. Upon successful authentication, the main application state is updated, and a JWT is stored in the browser to authorize subsequent API requests. Protected routes and user-specific actions, such as viewing the Settings or accessing other parts of the dashboard, are contingent on a valid authentication state.
Architecture Overview
The authentication system is split between the client-side React application and the server-side FastAPI application. The frontend handles user interaction and state management, while the backend is responsible for credential verification, token generation, and user data persistence.
This diagram shows the high-level components involved in the authentication process.
*LoginView.tsx**: Renders the login form and captures user credentials.
App.tsx: Manages the global authentication state (isAuthenticated) and routes the user to theLoginViewor the mainLayout.SettingsView.tsx: Allows authenticated users to update their profile and change their password.api.ts: A service module that centralizes all API calls to the backend, including an Axios interceptor to attach the JWT to requests.main.py: The FastAPI backend containing all authentication-related endpoints, logic for password hashing, and JWT management.users.json: A JSON file acting as the user database.
Sources: frontend/src/App.tsx, frontend/src/components/LoginView.tsx, backend/main.py, frontend/src/services/api.ts
Authentication Flow
The authentication process follows a standard token-based flow. The user provides credentials, the frontend sends them to the backend, and upon successful validation, the backend returns a JWT. This token is then stored on the client and used for all subsequent authenticated requests.
The following sequence diagram illustrates the login process.
Backend Implementation (FastAPI)
The backend is built with FastAPI and handles all core security operations.
Sources: backend/main.py
API Endpoints
The following endpoints are defined in main.py to manage user authentication and profiles.
| Method | Endpoint | Description | Protected |
|---|---|---|---|
POST | /api/login | Authenticates a user and returns a JWT. | No |
GET | /api/profile | Retrieves the current user's profile. | Yes |
PUT | /api/profile | Updates the current user's profile. | Yes |
POST | /api/change-password | Changes the current user's password. | Yes |
Sources: backend/main.py:189, backend/main.py:223, backend/main.py:233, backend/main.py:254
Data Models
Pydantic models are used for request and response validation.
Sources: backend/main.py:53-69
Security and JWT
The application employs JWT for securing endpoints.
- Password Hashing: Passwords are hashed using
PBKDF2-HMAC-SHA256with a salt and 100,000 iterations. Thehash_passwordandverify_passwordfunctions manage this process. - JWT Configuration: Tokens are generated using the
HS256algorithm. The token has an expiration time of 24 hours (1440 minutes). - Endpoint Protection: The
get_current_userdependency is used on protected routes. It decodes theBearertoken from theAuthorizationheader, validates its signature and expiration, and retrieves the user fromusers.json.
| Configuration | Value |
|---|---|
SECRET_KEY | your-secret-key-here... (hardcoded) |
ALGORITHM | HS256 |
ACCESS_TOKEN_EXPIRE_MINUTES | 1440 (24 hours) |
| Hashing Function | hashlib.pbkdf2_hmac('sha256', ...) |
| Hashing Iterations | 100000 |
Sources: backend/main.py:33-36, backend/main.py:75-93, backend/main.py:157-178
User Data Storage
User accounts are stored in a simple users.json file. The load_users function reads from this file. If the file does not exist, it creates one with a default admin user.
The structure of a user entry is as follows:
A default user is created if users.json is not found:
- Username:
admin - Password:
admin123
Sources: backend/main.py:126-137, frontend/src/components/DocumentationView.tsx:90-97
Frontend Implementation (React)
The frontend, built with React and TypeScript, is responsible for the user interface, state management, and communication with the backend API.
Core Components
App.tsx: The root component that manages the global authentication state (isAuthenticated). It conditionally rendersLoginViewor the mainLayoutbased on this state. It also contains thehandleLoginandhandleLogoutfunctions.LoginView.tsx: A dedicated component for the login page. It contains the form for username and password, handles form submission, displays error messages, and calls theonLoginprop passed fromApp.tsx.SettingsView.tsx: A component within the main layout that allows authenticated users to update their profile information (email,display_name) and change their password by providing the old and new passwords.Layout.tsx: The main application shell which includes the sidebar and header. The header contains the logout button, which triggers theonLogoutfunction.
Sources: frontend/src/App.tsx:38-57, frontend/src/components/LoginView.tsx, frontend/src/components/SettingsView.tsx, frontend/src/components/Layout.tsx
API Service and Token Handling
All interactions with the backend are handled through a dedicated service module.
Sources: frontend/src/services/api.ts
Token Management
Helper functions are provided to manage the JWT in the browser's localStorage.
| Function | Description |
|---|---|
getToken() | Retrieves the JWT from localStorage. |
setToken() | Stores the JWT in localStorage. |
clearToken() | Removes the JWT from localStorage. |
Sources: frontend/src/services/api.ts:6-8
Axios Interceptor
An Axios request interceptor automatically adds the JWT as a Bearer token to the Authorization header for every outgoing request, ensuring that all API calls to protected endpoints are authenticated.
// frontend/src/services/api.ts:11-19
axios.interceptors.request.use(
(config) => {
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
Sources: frontend/src/services/api.ts:11-19
API Functions
The api object in api.ts exposes methods that map directly to the backend authentication endpoints.
| Function | HTTP Request | Description |
|---|---|---|
login() | POST /api/login | Sends credentials and stores the token. |
logout() | (client-side) | Clears the token from localStorage. |
getProfile() | GET /api/profile | Fetches the current user's profile data. |
updateProfile() | PUT /api/profile | Updates user's email and display name. |
changePassword() | POST /api/change-password | Submits old and new passwords to update. |
Sources: frontend/src/services/api.ts:70-90