From 522740bc9e54b88815c49e7138ca5c6b34a8f1a7 Mon Sep 17 00:00:00 2001 From: RubenRWU Date: Wed, 6 May 2026 15:27:00 +0200 Subject: [PATCH] add codex skill --- .codex | 0 codex/README.md | 84 +++++++++++++++ codex/skills/onyva-login/SKILL.md | 171 ++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+) create mode 100644 .codex create mode 100644 codex/README.md create mode 100644 codex/skills/onyva-login/SKILL.md diff --git a/.codex b/.codex new file mode 100644 index 0000000..e69de29 diff --git a/codex/README.md b/codex/README.md new file mode 100644 index 0000000..6084687 --- /dev/null +++ b/codex/README.md @@ -0,0 +1,84 @@ +# Codex-Version + +Dieses Repo enthält unter [codex/skills/onyva-login/SKILL.md](/home/ruben/PycharmProjects/onyva-login-skill/codex/skills/onyva-login/SKILL.md) eine Codex-kompatible Version des bestehenden Claude-Skills. + +## Lokale Nutzung in Codex + +Lege den Skill lokal in deinem Codex-Home unter `skills/onyva-login/` ab, sodass dort eine `SKILL.md` liegt. Wenn du ihn aus diesem Repo kopieren willst: + +```bash +mkdir -p ~/.codex/skills/onyva-login +cp /home/ruben/PycharmProjects/onyva-login-skill/codex/skills/onyva-login/SKILL.md ~/.codex/skills/onyva-login/SKILL.md +``` + +Danach kannst du in Codex z. B. schreiben: + +```text +Nutze den Skill onyva-login und integriere den zentralen Login in dieses Projekt. +``` + +## Upload nach Gitea mit Token + +### 1. Persönlichen Access Token erzeugen + +In Gitea: + +1. Profilbild oben rechts öffnen +2. `Settings` +3. `Applications` +4. `Generate New Token` +5. Einen Namen vergeben, z. B. `codex-push` +6. Mindestens `repo`- bzw. Schreibrechte auf das Ziel-Repository geben +7. Token direkt kopieren, weil Gitea ihn danach meist nicht mehr vollständig zeigt + +### 2. Remote mit Token setzen + +Empfohlen ist ein temporärer Push per HTTPS mit Token: + +```bash +git remote add gitea https://:@gitea.onyva.dev//.git +``` + +Beispiel: + +```bash +git remote add gitea https://ruben:DEIN_TOKEN@gitea.onyva.dev/Onyva/onyva-login-skill.git +``` + +Falls `gitea` schon existiert: + +```bash +git remote set-url gitea https://:@gitea.onyva.dev//.git +``` + +### 3. Commit und Push + +```bash +git add codex/README.md codex/skills/onyva-login/SKILL.md +git commit -m "Add Codex version of onyva-login skill" +git push gitea main +``` + +### 4. Token nicht im Remote behalten + +Nach dem Push den Remote wieder ohne Token setzen, damit der Token nicht in `git remote -v` sichtbar bleibt: + +```bash +git remote set-url gitea https://gitea.onyva.dev//.git +``` + +## Sicherere Alternative mit Credential Helper + +Statt den Token in der URL zu speichern: + +```bash +git remote add gitea https://gitea.onyva.dev//.git +git push gitea main +``` + +Dann bei der Abfrage: + +- Benutzername: dein Gitea-Username +- Passwort: dein persönlicher Access Token + +Wenn dein System einen Credential Helper nutzt, wird der Token dort gespeichert statt in der Remote-URL. diff --git a/codex/skills/onyva-login/SKILL.md b/codex/skills/onyva-login/SKILL.md new file mode 100644 index 0000000..e3a4128 --- /dev/null +++ b/codex/skills/onyva-login/SKILL.md @@ -0,0 +1,171 @@ +--- +name: onyva-login +description: Integriert den zentralen Onyva Dev Login (OIDC/SSO) in ein bestehendes Projekt. Verwende diesen Skill, wenn der Nutzer Onyva Login, OIDC, SSO, Auth-Integration oder /onyva-login in einem Projekt umsetzen will. +--- + +Integriere den zentralen Onyva Dev Login (OIDC/SSO unter `https://login.onyva.dev`) in das aktuelle Projekt. + +## Workflow + +1. Analysiere zuerst das Projekt. + Prüfe Framework, Routing, bestehende Auth-Logik, Session-Handling und Env-Konfiguration, bevor du Code änderst. + +2. Kläre fehlende Eingaben nur dann, wenn sie nicht aus dem Repo ableitbar sind. + Du brauchst: + - `OIDC_CLIENT_ID` + - `OIDC_CLIENT_SECRET` + - `OIDC_REDIRECT_URI` + - `OIDC_LOGOUT_REDIRECT_URI` + - welche Routen geschützt sein sollen und welche öffentlich bleiben + +3. Implementiere die Integration passend zum vorhandenen Stack. + +4. Aktualisiere `.env.example` oder die äquivalente Konfiguration. + +## Technische Vorgaben + +### Auth-Server + +- Issuer / Basis-URL: `https://login.onyva.dev` +- Discovery: `https://login.onyva.dev/.well-known/openid-configuration` + +| Endpunkt | Methode | Zweck | +|---|---|---| +| `/oauth/authorize` | GET | Login starten | +| `/oauth/token` | POST | Code gegen Tokens tauschen | +| `/oauth/userinfo` | GET | Nutzerinfos per Bearer Token | +| `/oauth/jwks.json` | GET | Public Keys (RS256) | +| `/logout` | GET | Zentrales Logout | + +### Login starten + +Generiere `state` (mindestens 16 Zeichen, zufällig) und `code_verifier` (PKCE), speichere beide serverseitig in der Session. Dann Weiterleitung zu: + +```text +GET https://login.onyva.dev/oauth/authorize + ?response_type=code + &client_id={OIDC_CLIENT_ID} + &redirect_uri={OIDC_REDIRECT_URI} + &scope=openid profile email + &state={state} + &code_challenge={BASE64URL(SHA256(code_verifier))} + &code_challenge_method=S256 +``` + +`state` ist Pflicht. Ohne `state` kommt im Callback kein `state` zurück. + +### Callback verarbeiten + +```python +def callback(request): + if request.params.get("state") != session.pop("oauth_state", None): + return error("State mismatch") + + if "auth_disabled" in request.params: + session["user"] = {"auth_disabled": True} + return redirect("/") + + resp = http_post("https://login.onyva.dev/oauth/token", data={ + "grant_type": "authorization_code", + "code": request.params["code"], + "redirect_uri": OIDC_REDIRECT_URI, + "client_id": OIDC_CLIENT_ID, + "client_secret": OIDC_CLIENT_SECRET, + "code_verifier": session.pop("pkce_verifier"), + }) + tokens = resp.json() + + claims = decode_jwt(tokens["id_token"]) + session["user"] = { + "sub": claims["sub"], + "email": claims["email"], + "name": claims["name"], + "user_type": claims["user_type"], + "app_roles": claims["app_roles"], + } + return redirect("/") +``` + +Nach erfolgreichem Callback nie auf `/auth/*` zurückleiten. `return_to` immer auf `/` oder eine echte App-Seite normalisieren. + +### JWT Claims + +```json +{ + "sub": "user:42", + "email": "nutzer@onyva.de", + "name": "Max Mustermann", + "user_type": "employee", + "app_roles": ["admin"], + "iss": "https://login.onyva.dev", + "aud": "mein-client-id", + "exp": 1700000000 +} +``` + +### Logout + +```python +def logout(request): + session.clear() + return redirect( + f"https://login.onyva.dev/logout" + f"?post_logout_redirect_uri={urllib.parse.quote(OIDC_LOGOUT_REDIRECT_URI)}" + ) +``` + +`post_logout_redirect_uri` muss absolut sein (`https://...`). + +### Auth-Mode-Verhalten + +| auth_mode | Auth-Server-Verhalten | Client-Verhalten | +|---|---|---| +| `required` | 403 wenn keine Mitgliedschaft | Fehlermeldung anzeigen | +| `optional` | Code für jeden angemeldeten Nutzer; `app_roles` ggf. leer | App entscheidet selbst | +| `disabled` | Sofort zurück mit `?auth_disabled=1` | Kein Login-Dialog, alle Funktionen offen | + +### Entwicklungsmodus + +```python +def require_auth(request): + if not AUTH_ENABLED: + return { + "sub": "user:0", + "email": "dev@local", + "name": "Dev", + "user_type": "employee", + "app_roles": ["admin"], + } +``` + +### Env-Variablen + +```env +OIDC_ISSUER=https://login.onyva.dev +OIDC_CLIENT_ID= +OIDC_CLIENT_SECRET= +OIDC_REDIRECT_URI= +OIDC_LOGOUT_REDIRECT_URI= +AUTH_ENABLED=true +``` + +## Fallstricke + +- `state` immer mitsenden und validieren +- Redirect URI muss exakt mit dem Eintrag im Admin-Panel übereinstimmen +- Token-Endpunkt mit `application/x-www-form-urlencoded`, nicht JSON +- Session-Middleware korrekt aktivieren +- Öffentliche Routen explizit vom Auth Guard ausnehmen +- Kein Redirect zurück auf `/auth/*` + +## Checkliste + +- [ ] Env-Variablen ergänzt und `.env.example` aktualisiert +- [ ] Redirect URI im Admin-Panel eingetragen +- [ ] Login-Route mit `state` und PKCE gebaut +- [ ] Callback validiert `state` und tauscht Code gegen Tokens +- [ ] Claims landen in der Session +- [ ] Logout löscht lokale Session und ruft zentrales Logout auf +- [ ] Geschützte und öffentliche Routen sauber getrennt +- [ ] `AUTH_ENABLED=false` für lokale Entwicklung berücksichtigt +- [ ] `auth_disabled=1` Fall behandelt