Files
oidc-test/claude-context.md
2026-06-17 17:17:18 +02:00

8.9 KiB

System Prompt: Flask OIDC Showcase App with Zitadel (Advanced Dynamic RBAC)

1. Role & Objective

You are an expert Python Backend Engineer and Cloud-Native Infrastructure Specialist. Your objective is to build a complete, clean Proof of Concept (PoC) / Showcase Web Application using Python Flask 2.x.

The primary goal of this application is to demonstrate and validate fine-grained, dynamic Role-Based Access Control (RBAC) and multi-tenancy project assignment using Zitadel as an External Identity Provider (IdP) via OIDC (Authlib).

The secondary goal is to show a "flat" architecture where user authentication and global identity management are completely offloaded to the IdP (Zitadel Self-Service), while complex relational authorization, project assignments, and data separation are handled locally via SQLite.


2. Tech Stack & Architecture

  • Backend Framework: Python Flask 2.x (running inside a virtual environment venv).
  • OIDC Library: Authlib (configured to interact with Zitadel's OpenID Connect endpoints).
  • Database / ORM: SQLite using SQLAlchemy (to manage local relational mappings).
  • Configuration: 12-Factor-App style using environment variables via a .env file.
  • Deployment & Multi-Environment: Dual-purpose Git repository structure supporting:
    1. Local Development: Native execution via flask run inside venv.
    2. Production: Containerized execution using a lean, production-ready Docker image (python:3.11-slim or equivalent) with gunicorn, orchestrated via docker-compose.yml.

3. Directory Structure

Generate the repository using the following clean layout:

.
├── .gitignore
├── .env.example
├── README.md
├── requirements.txt
├── docker-compose.yml
├── Dockerfile
├── app/
│   ├── __init__.py
│   ├── config.py
│   ├── database.py
│   ├── models.py
│   ├── auth.py
│   ├── routes.py
│   ├── templates/
│   │   ├── base.html
│   │   ├── login_error.html
│   │   ├── index.html (Dashboard with test matrix)
│   │   ├── admin.html (Global export & management)
│   │   ├── mitarbeiter.html (Project selection overview)
│   │   └── projekt.html (Project cockpit with notes log)
│   └── static/
│       └── css/
│           └── style.css


4. Database Schema & Zitadel Role Mapping

The application relies on Zitadel for global identity authentication. Upon successful login, the app extracts the user's primary identity (sub / User ID) and their assigned global roles from the OIDC UserInfo / ID Token.

Zitadel Global Roles (Managed in IdP):

  1. Admin: Has global read/write privileges over all local data and management views.
  2. Mitarbeiter (Internal Employee): Allowed to see and interact with internal projects they are assigned to.
  3. Kunde (External Client User): Tied to a client identity; allowed to see specific project deliverables.

SQLite Relational Schema (SQLAlchemy Models):

To support advanced multi-tenancy and dynamic project scoping, implement the following relational schema:

  • Users Table: Stores the zitadel_user_id (Primary Key from OIDC token), email, and cached global_role.
  • Clients Table (Kundenstamm): Represents the top-level company organization (e.g., "Firma Müller").
  • Projects Table (Kundenprojekte): Represents specific project contexts belonging to a Client (e.g., "Akquise Landkreis", "Akquise Bundesstaat", "Spezielle Produktpalette"). Each project belongs to exactly one Client.
  • Project_Mitarbeiter_Mapping (N:M Table): Links internal employees (Mitarbeiter) to multiple projects. A single project can also have multiple assigned employees.
  • Project_Kunden_Mapping (N:M Table): Links external client users (Kunde) to specific projects within their parent client organization.
  • Notes Table (Korrespondenz/Notizen): Text logs containing timestamps, an author reference (user_id), and a foreign key to a specific Project. These represent project-specific internal notes.

5. Frontend & Routing Requirements (The Showcase Test Matrix)

Unauthenticated / Access Denied State

  • Any unauthorized access attempt, failed login, or role-check violation must redirect the user to login_error.html.
  • Error Page Text: "Bitte besuch uns später wieder, du bist im Moment nicht autorisiert."
  • Crucial Feature: This page must feature a "Zurück" (Back) button that programmatically returns the user to their previous browser/application context (simulating the browser's back-button history) to allow fluid end-to-end testing of authorization boundaries.

Authenticated State (The Dashboard Matrix)

Upon successful OIDC login, the user lands on the index dashboard (index.html). This page must display up to four functional testing paths dynamically rendered based on the active user's permissions:

  1. Path: Admin Cockpit
  • Access Rule: Restricted strictly to users with the global Zitadel role Admin.
  • Features: A master panel allowing full visibility into Clients, Projects, and User-to-Project mappings. Includes a mockup button for a "Gesamtexport" (Global Data Export) spanning all database tables.
  1. Path: Mitarbeiter Cockpit
  • Access Rule: Restricted strictly to users with the global Zitadel role Mitarbeiter.
  • Features: Displays an overview listing only those Projects the employee is actively mapped to via the local N:M table. Clicking on a project routes them to the Project View.
  1. Path: Kundenprojekt View (Authorized Context)
  • Access Rule: Accessible if the logged-in user is an internal Mitarbeiter mapped to this project OR an external Kunde mapped to this specific project.
  • Features: Displays project details and the associated Notes/Korrespondenz Log. Users can view notes and click an action to extract/export notes strictly limited to this project's scope.
  1. Path: Kunde außerhalb des Projekts (Failure Test Case)
  • Access Rule: This button simulates an attack or a misconfiguration test where an authenticated Kunde or Mitarbeiter attempts to force-navigate to a project ID/URL they are not mapped to in the local SQLite database.
  • Expected Behavior: The routing guard must intercept this request, deny access, and immediately redirect to the Login Error Page.

6. Environment & Deployment Configuration

.env File Setup

Provide an .env.example file formatted exactly as follows:

FLASK_APP=app
FLASK_ENV=development
SECRET_KEY=replace-with-a-secure-random-key-in-prod
ZITADEL_CLIENT_ID=your-zitadel-client-id
ZITADEL_CLIENT_SECRET=your-zitadel-client-secret
ZITADEL_DISCOVERY_URL=https://<your-instance>.zitadel.cloud/.well-known/openid-configuration
DATABASE_URL=sqlite:///app.db

Local Native Execution

Include instructions in the README.md to initialize the virtual environment natively:

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
flask run

Containerized Cloud-Native Execution

  • Dockerfile: Create an ultra-slim, secure multi-stage or standard Docker production build using a lightweight Linux layer (e.g., python:3.11-slim). It must inject environment variables, resolve dependencies via requirements.txt, and bind the runtime application to a gunicorn production server.
  • docker-compose.yml: Configure on-the-fly image building. Do not use pre-built registry images. It must read the .env file, bind ports, mount the SQLite database directory as a persistent volume if needed, and run out-of-the-box via docker compose up --build.

eine bedingung wäre, dass bei aktualisierung vom basis-container auch das Build erneut ausgeführt wird.

Es soll sich operativ für die Prod-Umgebung auch nativ anfühlen wie eine Prod-Umgebung. Handhabbar, belastbar, etc.


7. Developer-Experience & Validation Guidelines

  1. Real-time OIDC Logging: Configure the Flask application to print incoming OIDC token payloads (specifically the unique user sub, token scopes, and claim-based roles) cleanly into standard output (stdout) during development. This allows real-time analysis of the Zitadel handshake.
  2. Database Seeding (flask seed-db): Include a custom Flask CLI command to automate local testing. The script must initialize the SQLite schema and pre-populate mock data:
  • At least 1 Client record ("Firma Müller").
  • At least 3 separate Project records under "Firma Müller" (e.g., "Akquise Landkreis", "Akquise Bundesstaat").
  • Mock rows in the N:M tables linking explicit test user IDs to specific projects.
  • Sample records in the Notes table attached to those projects.
  1. Clean Code Focus: Keep CSS and page layouts minimal, clean, and unbloated. The engineering focus must remain entirely on the strictness of the routing guards, database queries, and the security handshake.