# CLAUDE.md This file provides guidance to AI assistants when working with code in this repository. ## Project Purpose A production-ready OpenID Connect (OIDC) Identity Provider (IdP) built in Flask. It is designed for self-hosting and homelab environments, uses a PostgreSQL database, and is deployed via Docker. It implements the full Authorization Code Flow with advanced user management. ## How to Run the Server The primary way to run the server is with Docker Compose. ```bash # 1. Copy the production environment template cp .env.production .env # 2. (Optional) Edit the .env file, especially OIDC_ISSUER nano .env # 3. Build and start the services (in detached mode) ./deploy.sh ``` The server will be available on port 5000, with a PostgreSQL database running in a separate container. For local development outside of Docker, see the `README.md`. ## Architecture Overview ### Configuration (`config.py`, `.env`) - **Environment-based**: The application loads its configuration based on the `FLASK_ENV` environment variable (`development` or `production`). - **`config.py`**: Contains three classes: `DevelopmentConfig`, `ProductionConfig`, and `TestingConfig`. The `get_config()` function returns the appropriate class. - **`.env` file**: All secrets (like `SECRET_KEY`, `DATABASE_URL`) and environment-specific settings are loaded from this file using `python-dotenv`. - **Validation**: `ProductionConfig` validates that all required environment variables are set, preventing startup with an incomplete configuration. ### Main Application (`oidc_server.py`) - **Flask App**: The core of the application. It initializes the database, rate limiter, and loads the configuration. It also initializes `Flask-Migrate` for database schema migrations. - **Blueprints**: The application is structured with Flask Blueprints for modularity: - **OIDC Endpoints**: `/authorize`, `/token`, `/userinfo`, `/.well-known/openid-configuration`. - **User-facing pages**: `/login`, `/register`, `/change-password`, `/dashboard`. - **Admin Panel**: A complete admin section under `/admin/...` protected by an `@admin_required` decorator. - **Templates**: All HTML templates are stored as strings in `templates.py` and `admin_templates.py` and rendered with `render_template_string` for simplicity. ### Database Layer (`models.py`) SQLAlchemy ORM models define the database schema. 1. **`User` Model**: - Stores user credentials with **bcrypt-hashed** passwords. - Implements roles (`role` field) and a flexible, JSON-based `permissions` system. - Helper methods like `set_password()`, `check_password()`, `get_permissions()`, `has_permission()`. - `is_admin` and `is_active` flags for access control. 2. **`Client` Model**: - Stores OIDC client applications. - `client_id` is the public identifier. - `client_secret_hash` stores the hashed client secret using bcrypt. - `redirect_uris` and `allowed_scopes` are stored as JSON strings. 3. **`AuthorizationCode` Model**: - Stores temporary authorization codes with a configurable TTL (Time To Live). - `is_valid()` method checks if the code is expired or has already been used. - One-time use is enforced by the `used` flag. 3. **`AccessToken` Model**: - Stores issued access tokens with a configurable TTL. - Can be invalidated using the `revoked` flag. 4. **`AuditLog` Model**: - **New**: Logs critical security events. - A class method `AuditLog.log()` is used to easily create new log entries. - Tracks actions like `login_success`, `login_failed`, `user_created`, `user_deleted`, etc. - Stores IP address, User-Agent, and other relevant details. ### Security Features - **Rate Limiting**: `Flask-Limiter` is used to protect sensitive endpoints like `/login`, `/admin/login`, and `/token` from brute-force attacks. - **Audit Logging**: All important user and admin actions are logged to the `audit_logs` table for security analysis. - **Password Security**: Passwords are never stored in plaintext. `bcrypt` is used for hashing. - **Admin Protection**: The admin area is protected by a decorator (`@admin_required`) that checks for a valid admin session and ensures the user has admin privileges. ## Key Implementation Details - **OIDC Flow**: The standard flow is implemented across `/authorize` and `/token`. The ID token is signed using **RS256** with a private key. The corresponding public key is exposed via the `/jwks` endpoint. - **Database Migrations**: The database schema is managed by `Flask-Migrate` (Alembic). The `flask db upgrade` command applies migrations, and the `flask seed` command populates the database with initial users. - **Token Cleanup**: `cleanup_expired_tokens()` provides a way to periodically remove expired tokens from the database. ## Security Status This is an overview of security features from the `TODO.md` file. - ✅ **bcrypt password hashing** - ✅ **Persistent database storage** - ✅ **User self-service registration & password change** - ✅ **Rate Limiting** on critical endpoints - ✅ **Audit Logging** for security-relevant events - ✅ **Environment-based config** (no secrets in code) - ✅ **Asymmetric JWT signing (RS256)** - ✅ **Database migrations (Alembic)** - ✅ **Multi-client support** (managed in the database) - ✅ **Docker support** with a non-root user - ⚠️ **Still needs for full OIDC compliance and higher security**: - Refresh Tokens. - PKCE support for public clients (SPAs, mobile apps).