feat: Backend mit OIDC-Anmeldung, Apps und Einstellungen im Server

Aus der statischen Seite wird ein Go-Binary mit eingebetteter Oberfläche.
Grund: Apps über .env zu pflegen wurde unübersichtlich, und kosmetische
Einstellungen sollen auf jedem Gerät gleich sein.

- Anmeldung über den eigenen OIDC-Anbieter (PocketID), mit PKCE. Ohne
  Anmeldung gibt es nichts zu sehen – auch keine App-Liste.
- Sitzung als signiertes Cookie ohne Gegenstück im Server; Schreibzugriffe
  zusätzlich über ein lesbares CSRF-Cookie abgesichert
- Apps werden in der Oberfläche angelegt und bearbeitet, nicht mehr in der
  .env. Der Server prüft jeden Eintrag und meldet zurück, was er behält.
- Einstellungen liegen je Nutzer im Server; localStorage ist nur noch der
  Vorschuss, damit die Röhre beim Laden nicht in der falschen Farbe blitzt
- die Leiste holt die App-Liste aus /api/apps – freigegeben sind allein die
  Ursprünge, die selbst als App eingetragen sind
- Tests fahren einen echten OIDC-Anbieter hoch und gehen den Anmeldeweg
  einmal ganz durch

Ohne HONEYOS_OIDC_ISSUER läuft alles offen – für die Entwicklung, mit
deutlicher Warnung beim Start.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-08-24 15:20:55 +02:00
1 parent 84cc5d619e
commit 283f9a1850
20 files changed
+1831 -438

No files matched your search

+33 -75
View File
@@ -1,88 +1,46 @@
# ─────────────────────────────────────────────────────────────────────────────
# HoneyOS — Konfiguration
# HoneyOS
#
# cp .env.example .env && anpassen
# cp .env.example .env && ausfüllen
# docker compose pull && docker compose up -d
#
# Alles hier landet beim Containerstart in config.json und wird vom Browser
# gelesen. Das heißt: **es ist öffentlich.** Adressen und Namen gehören hier
# hinein, Geheimnisse niemals — HoneyOS hat kein Backend, das eines hüten
# könnte. Nach jeder Änderung: docker compose up -d (Neustart genügt).
# Apps werden NICHT hier eingetragen — die legst du in der Oberfläche an
# (Einstellungen → Programme). Sie liegen im Server unter /data/honeyos.json.
# ─────────────────────────────────────────────────────────────────────────────
HONEYOS_PORT=8088
# Anzeigename, solange keine App einen besseren nennt (siehe _ME weiter unten).
HONEYOS_USER=marc
HONEYOS_HOSTNAME=honeyos
HONEYOS_VERSION=0.1
# Wo HoneyOS von außen erreichbar ist — ohne Schrägstrich am Ende.
# Daraus entsteht die Rückrufadresse: <PUBLIC_URL>/api/auth/callback
HONEYOS_PUBLIC_URL=https://os.honeyy.duckdns.org
# ── Apps ─────────────────────────────────────────────────────────────────────
# Durchnummeriert ab 1. Eine App entsteht durch ihre _URL — fehlt die, wird die
# Nummer übersprungen. Bis zu 12 Stück.
#
# _URL Pflicht. Wohin der Start springt.
# _ID Kurzname, klein. Muss zu data-app der Leiste passen. Standard: appN
# _NAME Beschriftung. Standard: die ID in Großbuchstaben
# _SUBTITLE Zeile darunter auf der Kachel
# _GLYPH Symbol: cloud | note | box | chip | folder | gear
# _KEY Zifferntaste zum Starten im Terminal-Modus
# _ME optional, siehe „Anmeldung" unten
# _TOKEN_KEY optional, siehe „Anmeldung" unten
# Unterschreibt das Sitzungscookie. Mindestens 32 Zeichen.
# openssl rand -hex 32
# Wird der Wert getauscht, sind alle Anmeldungen weg — sonst passiert nichts.
HONEYOS_SESSION_SECRET=
HONEYOS_APP_1_ID=aether
HONEYOS_APP_1_NAME=AETHER
HONEYOS_APP_1_SUBTITLE=Cloud & Dateien
HONEYOS_APP_1_URL=https://cloud.honeyy.duckdns.org
HONEYOS_APP_1_GLYPH=cloud
HONEYOS_APP_1_KEY=1
HONEYOS_APP_1_ME=/api/v1/auth/me
# Wo die Daten liegen (Apps + Einstellungen je Nutzer, eine JSON-Datei).
# Das ist das Einzige, was gesichert werden muss.
HONEYOS_DATA_DIR=/srv/honeyos
HONEYOS_APP_2_ID=inknote
HONEYOS_APP_2_NAME=INKNOTE
HONEYOS_APP_2_SUBTITLE=Notizen & Zeichnen
HONEYOS_APP_2_URL=https://notes.honeyy.duckdns.org
HONEYOS_APP_2_GLYPH=note
HONEYOS_APP_2_KEY=2
HONEYOS_APP_2_ME=/api/auth/me
HONEYOS_APP_2_TOKEN_KEY=inknote_token
# ── Anmeldung ────────────────────────────────────────────────────────────────
# Leerer HONEYOS_OIDC_ISSUER = KEINE Anmeldung, jeder kommt rein. Das ist zum
# Entwickeln gedacht und gehört nicht ins offene Netz.
#
# In PocketID einen Client anlegen und dort als Rückrufadresse exakt
# https://os.honeyy.duckdns.org/api/auth/callback
# eintragen. HoneyOS schickt PKCE mit, ein Client-Geheimnis braucht es
# trotzdem — also keinen „public client" anlegen.
HONEYOS_OIDC_ISSUER=https://id.honeyy.duckdns.org
HONEYOS_OIDC_CLIENT_ID=honeyos
HONEYOS_OIDC_CLIENT_SECRET=
# Nur nötig, wenn die Rückrufadresse von PUBLIC_URL abweicht:
# HONEYOS_OIDC_REDIRECT_URL=
# HONEYOS_APP_3_ID=paperwall
# HONEYOS_APP_3_URL=https://…
# HONEYOS_APP_3_GLYPH=box
# HONEYOS_APP_3_KEY=3
# Beschriftung des einen Knopfes auf dem Anmeldeschirm.
HONEYOS_BUTTON_LABEL=Anmelden mit PocketID
# ─────────────────────────────────────────────────────────────────────────────
# Anmeldung — was HoneyOS kann und was nicht
# ─────────────────────────────────────────────────────────────────────────────
#
# HoneyOS meldet NIEMANDEN an. Es ist eine statische Seite; ein OIDC-Client
# bräuchte ein Backend und ein Client-Geheimnis, und beides gibt es hier nicht
# — absichtlich. Die Anmeldung bleibt Sache von Aether und InkNote, die beide
# an PocketID hängen.
#
# Was HoneyOS kann: **anzeigen**, wer angemeldet ist. Dafür ist _ME da — der
# Pfad, unter dem die App „wer bin ich" beantwortet. Relativ zu _URL oder
# absolut. Aus der Antwort wird der Anzeigename gefischt (display_name,
# displayName, name, username), verschachtelt unter `user` wird auch gefunden.
#
# Zwei Wege, wie das gelesen wird — und sie verhalten sich unterschiedlich:
#
# 1. Die Leiste IN der App (honeybar.js) fragt ihre eigene App.
# Gleicher Ursprung, also **funktioniert das sofort**, ohne dass an Aether
# oder InkNote etwas geändert werden muss.
#
# 2. Der Desktop auf os.… fragt über die Domaingrenze.
# Dafür muss die App diesen Ursprung erlauben, sonst blockt der Browser:
# InkNote: ALLOWED_ORIGINS=https://os.honeyy.duckdns.org
# Aether: CORS mit Access-Control-Allow-Credentials — noch nicht drin
# Ohne das bleibt die Anzeige einfach leer. Nichts geht kaputt, die
# Lampe „online" funktioniert weiter.
#
# _TOKEN_KEY brauchen nur Apps, die einen Bearer-Token im localStorage halten
# statt eines Cookies (InkNote tut das). Der Token ist pro Domain sichtbar —
# von os.… aus also NICHT lesbar. Für die Leiste in der App reicht es.
#
# Und wichtig: alle Adressen müssen unter derselben Domain liegen
# (…​.honeyy.duckdns.org). Sonst behandelt der Browser sie als fremde Site und
# schickt die Sitzung gar nicht erst mit.
# Zweiter Riegel neben den Gruppen in PocketID: nur diese Konten dürfen rein
# (Benutzername oder sub, kommagetrennt). Leer = jeder, den der Anbieter
# durchlässt.
# HONEYOS_ALLOWED_USERS=marc