Eine Web-Anwendung, die im Browser direkt mit der API spricht, hält Geräte-ID und Token im Browser. Wer den Token erbeutet, liest und ändert Daten mit den Rechten dieses Zugangs, bis jemand das Gerät löscht oder das Passwort ändert. Die Regeln unten halten dieses Risiko klein. Sie gelten für selbst geschriebenen Code genauso wie für Code aus einem Coding-Agenten.
Nur https
Basic Auth schickt Geräte-ID und Token bei jeder Anfrage mit. Sie sind dabei nur Base64-kodiert, nicht verschlüsselt. Erst https schützt sie auf dem Weg zum Server.
- Nimm als Server-Adresse nur Adressen mit
https://an. - Lehne Server-Adressen ab, die Zugangsdaten enthalten, etwa
https://name:passwort@…. - Liefere auch die Anwendung selbst über https aus. Nur beim Entwickeln auf dem eigenen Rechner unter
localhostgeht es ohne.
Zugangsdaten nie im Code
Geräte-ID und Token gibt der Benutzer beim Anmelden ein. Sie stehen nicht im Quelltext, nicht in einer Konfigurationsdatei im Repository und nicht in der Adresszeile.
Das Login-Passwort speichert die Anwendung nie. Am einfachsten legt der Benutzer das Gerätepasswort selbst an und gibt danach Geräte-ID und Token ein. Wo das in teamspace geht, zeigt Authentifizieren: Gerätepasswort & API-Token.
Dauerhaft speichern nur auf Wunsch
- Ohne ausdrücklichen Wunsch hält die Anwendung die Zugangsdaten nur für die laufende Sitzung, im Arbeitsspeicher oder in
sessionStorage. - In
localStoragelegt sie sie erst ab, wenn der Benutzer „Angemeldet bleiben“ wählt. - Abmelden löscht alles, was gespeichert war.
- Merkt sich die Anwendung sonst etwas, zum Beispiel eine laufende Zeitmessung, dann je Mitarbeiter und nicht je Gerät.
Besteht der Verdacht, dass ein Token abgegriffen wurde, löschst du das Gerät in den Persönlichen Einstellungen oder erzeugst über „Passwort ändern“ ein neues Passwort. Andere Geräte bleiben davon unberührt.
Ein eigener Zugang mit wenig Rechten
Über die API hat ein Zugang genau die Rechte, die die Person in der Oberfläche hat. Eine Web-Anwendung kann also alles, was ihr Benutzer darf, auch löschen.
- Leg für jede Anwendung ein eigenes Gerätepasswort an. Dann sperrst du sie einzeln, ohne andere Zugänge anzufassen.
- Teste neue Anwendungen mit einem Konto, das nur die Rechte hat, die die Anwendung braucht.
- Lass die Anwendung nachfragen, bevor sie etwas mit Folgen schreibt, etwa bevor sie einen offenen Punkt als erledigt markiert.
- Für Geräte ohne persönlichen Benutzer, etwa ein Terminal, ist die API-Zugangsberechtigung der richtige Zugang.
Warum die API keine zusätzliche Schranke ist und wie du Zugänge widerrufst, fasst API-Sicherheit & Berechtigungen zusammen.
Daten vom Server als Text ausgeben
Projektnamen, Beschreibungen und Kommentare tippen Menschen ein. Setzt eine Anwendung solche Texte als HTML in die Seite, kann ein präparierter Eintrag Skript ausführen und den Token auslesen.
- Gib Serverdaten immer als Text aus, in JavaScript mit
textContent, nie mitinnerHTML. In React verzichtest du aufdangerouslySetInnerHTML. - Zeig bei Fehlern den Text aus
messagean. Das Feldstacktraceenthält interne Angaben des Servers und gehört nicht in die Oberfläche. - Lade keine Skripte von fremden Servern. Ein eingebundenes Skript kann alles lesen, was deine Anwendung sieht, auch den Token.
Browserzugriff (CORS)
Liegt die Anwendung unter einer anderen Adresse als der Server, entscheidet der Browser anhand der CORS-Angaben des Servers, ob er die Antwort herausgibt. Die Anwendung muss deshalb nicht auf dem Server liegen, jeder Webspace mit https genügt. Bei einer Prüfung ohne Anmeldung am 2026-09-10 antworteten zwei Cloud-Server so. Die erlaubte Herkunft und die Methoden bestätigten sich vom 2026-09-10 bis 2026-09-14 auch mit Anmeldung an einer weiteren Installation (Version 2026.3-preview):
Access-Control-Allow-Origin: *: Aufrufe von jeder Adresse sind zugelassen.Access-Control-Allow-Headers: Content-Type, Authorization, If-None-Match: Der HeaderAuthorizationfür Basic Auth darf mitgeschickt werden.Access-Control-Allow-Methods: an der Liste/api/timeGETundPOST, am einzelnen Element/api/issue/{id}GET,PUTundDELETE.
Für deinen Code folgt daraus:
const antwort = await fetch(server + '/api/time;depth=1?worker=' + mitarbeiterId + '&date=' + tag, {
headers: { Authorization: 'Basic ' + btoa(geraeteId + ':' + token) }
});
if (antwort.status === 401) {
// Anmeldung abgelehnt. Die Antwort ist Text, kein JSON.
}
- Schick die Anmeldung im Header
Authorization, nicht über Cookies. Mitcredentials: 'include'gibt der Browser die Antwort nicht heraus, weil der Server*als Herkunft erlaubt. - Zusätzliche eigene Header, die nicht in der Liste stehen, lassen die Vorabprüfung des Browsers scheitern.
- Ändern mit
PUTgeht nur an der Adresse des einzelnen Elements, nicht an der Liste.
Häufige Probleme
Warum meldet der Browser einen CORS-Fehler, obwohl dieselbe Anfrage mit curl klappt?
Werkzeuge außerhalb des Browsers prüfen CORS nicht. Im Browser scheitert die Anfrage zum Beispiel an einem Header, der nicht in Access-Control-Allow-Headers steht, an einer Methode, die an dieser Adresse nicht erlaubt ist, oder an credentials: 'include'.
Warum meldet die Anwendung beim Speichern einen Netzwerkfehler, obwohl der Server erreichbar ist?
Wahrscheinlich hat der Server die Anfrage abgelehnt, etwa wegen eines Datums im falschen Format. Nicht jede Fehlerantwort trägt die CORS-Angaben, zum Beispiel 400 bei nicht lesbarem JSON. Dann gibt der Browser weder Status noch Meldung heraus. Sieh in teamspace nach, ob gespeichert wurde, und prüf die Formate im Leitfaden für Coding-Agenten.
Warum ist der Benutzer nach dem Schließen des Browsers abgemeldet? Die Anwendung hält die Zugangsdaten ohne „Angemeldet bleiben“ nur für die Sitzung. Das ist gewollt. Wer dauerhaft angemeldet bleiben möchte, wählt die Option beim Anmelden.
Verwandte Themen
- API-Sicherheit & Berechtigungen API Konzept
- Authentifizieren: Gerätepasswort & API-Token API Anleitung
- Zeiten über die API anzeigen und buchen API Übungen
- Die OpenAPI-Beschreibung nutzen API Referenz