Files
oicd/CLAUDE.md
2025-11-30 00:07:24 +01:00

5.4 KiB

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.

# 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.
  4. AccessToken Model:

    • Stores issued access tokens with a configurable TTL.
    • Can be invalidated using the revoked flag.
  5. 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).