feat: Betrieb hinter einem Anmelde-Proxy, Schlüssel für die App-Liste

Marc stellt Pangolin davor und will keinen zweiten Anmeldeschirm.

- HONEYOS_PROXY_AUTH=true: HoneyOS prüft nicht mehr selbst, der Start sagt
  deutlich, dass der Container dann nur über den Proxy erreichbar sein darf.
  Mit HONEYOS_USER_HEADER bekommt jeder Name seine eigenen Einstellungen.
- HONEYOS_APPS_KEY schützt /api/apps. Nötig, weil HoneyOS auf einer anderen
  Site liegt als die Apps (duckdns.org steht auf der Public-Suffix-Liste) –
  der Browser schickt die Sitzung dort nicht mit, und der Pfad muss im Proxy
  von der Anmeldung befreit sein.

Beim Durchspielen mit zwei echten Hostnamen fiel ein Loch auf: Ohne eigene
Anmeldung gilt jede Anfrage als angemeldet, also gab der Rückfall auf diese
Prüfung die Liste an jeden heraus – auch ohne oder mit falschem Schlüssel.
Der Rückfall greift jetzt nur noch, wo es wirklich eine Sitzung geben kann.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-08-24 22:09:37 +02:00
1 parent 905b136516
commit 1c3218939b
8 files changed
+382 -45

No files matched your search

+10 -1
View File
@@ -13,6 +13,10 @@
* data-Attribute am <script>:
* data-app (Pflicht) id der App, in der die Leiste steckt
* data-apps URL der App-Liste; ohne das /api/apps neben dem Skript
* data-key Schlüssel für die App-Liste. Nötig, wenn HoneyOS auf einer
* anderen Site liegt als die App: dann schickt der Browser die
* HoneyOS-Sitzung nicht mit, und ohne zweiten Ausweis bliebe die
* Leiste ohne Liste.
* data-home URL des HoneyOS-Desktops
* data-push "body" (Standard) schiebt den Seiteninhalt nach unten,
* "none" legt die Leiste darüber
@@ -46,6 +50,7 @@
// geladen wurde. Er gibt die Liste nur an angemeldete Browser heraus und
// nur an Ursprünge, die selbst als App eingetragen sind.
const appsUrl = d("apps", script ? new URL("../api/apps", script.src).href : "");
const appsKey = d("key", "");
let apps = DEFAULT_APPS;
@@ -270,7 +275,11 @@
try {
// credentials: die Sitzung liegt auf der HoneyOS-Domain, und die ist
// dieselbe Site wie diese hier — sonst käme das Cookie nicht mit.
const res = await fetch(appsUrl, { cache: "no-store", credentials: "include" });
const res = await fetch(appsUrl, {
cache: "no-store",
credentials: "include",
headers: appsKey ? { "X-HoneyOS-Key": appsKey } : {},
});
if (res.ok) {
const list = await res.json();
if (Array.isArray(list) && list.length) {
+5
View File
@@ -185,8 +185,13 @@ function glyphSvg(name) {
* ihr Wert steht in einem absichtlich lesbaren Cookie, das nur bekommt, wer
* die Seite wirklich geöffnet hat.
*/
/** Der Schlüssel für die App-Liste steht als Meta-Angabe in der Seite — der
* Server legt ihn dort hinein, wenn einer eingerichtet ist. */
const APPS_KEY = document.querySelector('meta[name="honeyos-key"]')?.content || "";
async function api(path, opts = {}) {
const headers = { ...(opts.headers || {}) };
if (APPS_KEY) headers["X-HoneyOS-Key"] = APPS_KEY;
if (opts.method && opts.method !== "GET") {
headers["Content-Type"] = "application/json";
const tok = cookie("honeyos_csrf");