[MEAN] Zu viele JWT-Decodings machen die Software langsam

Sithys

Captain Pro
Registriert
Dez. 2010
Beiträge
3.484
Moin zusammen,
ich bastel aktuell 'ne MEAN-Anwendung. Bin ziemlich gut voran gekommen die letzten Wochen, hänge jetzt aber an einem Brocken, von dem ich noch nicht weiß, wie ich ihn kleiner bekomme.

Die entwickelte Software ist doch ziemlich groß geworden und wurde zu guter letzt um ein ausführliches Rechtemanagement ergänzt - woher dann auch mein Problem rührt.

Etliche Menüpunkte und Funktionen sind an Rechte gebunden. Wenn also der View geladen wird, muss ich eine Prüfung der Rechte vornehmen und anschließend entsprechend Elemente ein- bzw. ausblenden. Zum Glück gibts *ngIf dachte ich mir und so habe ich meine navbar einfach mit *ngIf Abfragen gespickt, die wie folgt aussahen (Beispiel):

<divclass="dropdown-menu"aria-labelledby="navbarDropdown">
<aclass="dropdown-item" *ngIf="authService.isAdmin() || userRightsService.userHasRight('canCreateHardware')" [routerLink]="['/createHardware']" (click)="checkForRelog()">Anlegen</a>
<aclass="dropdown-item" *ngIf="authService.isAdmin() || userRightsService.userHasRight('canSearchHardware')[routerLink]="['/search']" (click)="checkForRelog()">Suchen</a>
</div>


Problem bei dem Ganzen ist allerdings, dass der userRightsService mir komplett um die Ohren fliegt. Jeder Seitenreload bringt eine Auslösung der Abfrage mit sich, bei jedem DOM-Event findet wohl ein rebuild der Navigation statt, weshalb stetig hunderte Requests an den userRightsService rausgehen. Der Service decodiert das Token im Hintergrund, prüft auf das Recht und liefert dann true oder false zurück.

Folge: Die ganze Anwendung ist sterbenslangsam, Firefox frisst 90% CPU Leistung und die Lust ist dahin.



Ich hab jetzt diverse Dinge probiert, mir fehlt aber der richtige Ansatz. Aktuell hab ich eine Krücke gebaut... einmalig werden die Rechte angefragt, wenn der User sich einloggt, anschließend gibts einen window.location.reload() und die Menüpunkte sind wie gewünscht da - fühlt sich aber nicht gut / richtig an.

Vielleicht gibts ja hier den ein oder anderen MEAN Spezi, der mir sagen kann, wie man so ein Problem am Besten lösen würde.
 
Zuletzt bearbeitet:
Ich musste nun erstmal googlen, was wohl MEAN ist, aber dein Quellcode verrät ja schon, dass es um Angular geht :)

Vorschlag:

Baue eine Strukturierte Directive welche ähnlich wie ngIf funktioniert.
In deinem userRightsService speicherst du die Berechtigungen in einer variablen zusätzlich zum token ab und definierst ein Subject, welches beim Einloggen/ausloggen/Rechteänderung getriggert wird.
Die neu erstellte Direktive abonniert das definierte Subject und prüft die Rechte dann jeweils wenn das Subject auslöst. Je nachdem ob Rechte vorhanden sind, wird der ViewContainer mittels der Directive geleert, oder das template neu angehängt.
 
Zuletzt bearbeitet:
Versuch mal eine Pipe statt Funktionsaufruf im ngIf zu benutzen. Das sollte das Reload Problem lösen.

Die Funktionsaufrufe werden bei jeder Änderung in der Komponente ausgeführt. Pipes aber nur wenn sich tatsächlich was am Input der Pipes ändert.
 
Also um das diagnostizieren zu können, denke ich, ist mehr Code notwendig. Hören die Anfragen an den Service irgendwann auf? Oder hast du evtl. ungewollt eine Rekursion erzeugt?
 
Zuletzt bearbeitet:
Um ehrlich zu sein, würde ich sowas nicht im Frontend machen. Wenn du Express verwendest, kannst du mit Hilfe von Template Engines das Menü auf dem Server rendern lassen, dann brauchste sowas nicht im Client machen. ich habe keine Ahnung wie kritisch deine Anwendung ist, aber wenn ich einfach nur die DevTools öffnen muss um zu sehen, dass es noch einen "/createHardware" endpoint gibt, dann kann ich diese URL auch so eingeben im Browser. Oder ich häng einfach den Debugger an die entsprechende Stelle und lass ein true bei "isAdmin()" zurück geben.....

Allgemein sollte man Security Zeug im Backend machen, alles andere ist quatsch.

Edit: Du kannst bei Angular auch Server Side Rendering direkt verwenden, wenn du keine Template Engine verwendest/verwenden willst.
 
Zuletzt bearbeitet:
Danke für Eure Antworten!

Ich habe meine Buttons und Menüpunkte zwischenzeitlich angepasst und die ganzen *ngIf entfernt. Die Prüfung erfolgt nun im OnInit auf die einzelnen Rechte, die kommen in Variablen und die werden dann im *ngIf geprüft - viel besser!


@benneque - wie funktioniert das mit den Pipes, hast Du da mal ein Beispiel für mich?

@kelox - kritisch ist ja immer so eine Sache... das Tool sollen hinterher die Mädels aus der Verwaltung nutzen. Wenn ich danach gegangen wäre, hätte ich einfach alles ohne Überprüfung so entgegen nehmen können aber man weiß ja nicht, wer im Netzwerk noch so herumschlurft ;-).
Die einzelnen Endpoints wirst Du im Quellcode nicht finden und die Rechte sind alle ordentlich im JWT verschlüsselt.

Das mit dem Debugger hab ich noch nie gesehen - wie läuft sowas ab? Die Antwort kommt ja vom Service, welcher Dir unbekannt ist. Und wie gesagt: Ich brauche diese Abfragen nur fürs Frontend... auf dem Server wird selbstverständlich erneut das Token validiert inkl. der Überprüfung auf das entsprechende Recht. Selbst wenn Du es also schaffst, isAdmin auf true zu setzen, siehst Du nur Menüs / Buttons aber keinerlei Daten oder sonstiges. Alle Get / Post Requests sind entsprechend abgesichert.

Trotzdem: Ich würde gerne mal sehen, wie sowas mit dem Debugger läuft - gibts da Videos zu?

SSR hab ich noch nie gemacht, da muss ich mich im nächsten Projekt evtl. mal ranwagen.
 
Hier ist die Doku zu den Pipes: https://angular.io/guide/pipes
Am Ende solltest du dann sowas im Code stehen haben: *ngIf="'canCreateHardware' | userHasRight"

Dein Sicherheitssystem klingt nach deiner letzten Ausführung ziemlich overengineered und overcomplicated.
Warum benutzt du verschlüsselte JWTs? Benutz einfach die Variante mit Klartext und Signatur.

Die Rechte und Endpoints dürfen selbstverständlich im Quellcode stehen.
Das Frontend kann prinzipiell so "unsicher" sein wie es will. Hier geht es nur darum, es dem Benutzer so bequem wie möglich zu machen.

Die eigentliche Sicherheit muss das Backend bereitstellen. Punkt.

Ob der Benutzer jetzt einen Bereich sieht, in dem keine Daten stehen, weil das Backend sie schützt. Oder der Benutzer den Bereich nicht sieht, hat was mit der Usability zu tun. Aber nicht mit der Sicherheit.
Das gilt natürlich nicht, wenn irgendwelche Firmengeheimnisse im Quellcode stehen, wie z.B. spezielle Datenstrukturen oder Algorithmen. Aber darum geht's hier schätzungsweise überhaupt nicht. (Und solche Daten sollten dann natürlich auch vom Backend geschützt sein)
 
Zuletzt bearbeitet:
Also ein klassischer JWT ist nicht verschlüsselt und das ist eigentlich auch nicht notwendig (hast du selbst noch eine Verschlüsselung "drangebaut"?).
Es ist überhaupt kein Problem wenn ein Nutzer sich Zugang zu den gesicherten Routes verschaffen kann, solang alle Daten vom Server mit dem Token geschützt sind.
 
Ich hab immer mit jwt.sign gearbeitet und mein genau das mit "Verschlüsselung". Im Standard ist das "Sign with default (HMAC SHA256)", deshalb sprech ich von Verschlüsselung - oder meinen wir was unterschiedliche Dinge?

Wenn das quasi so egal ist, dann könnte man ja für das Frontend ohne Probleme mit dem LocalStorage arbeiten, oder? Ich könnte beim Login die Werte prüfen, im LocalStorage ablegen und dann entsprechend die ganzen Abhängigkeiten daran koppeln. Nur ist mir keine Lösung geläufig, die so arbeitet?! Es soll ja hinterher nicht heißen, ich hätte mir keine Mühe gegeben.

Auf dem Server wird dann mit jwt.verify das ganze wieder aufgelöst->

PS: Leider ist die Code-Darstellung hier im Forum absolut gruselig, deshalb als Bild.

Bildschirmfoto 2018-05-03 um 08.48.01.png

Nach der Auflösung hol ich mir die UserID und guck dann in den Rechten auf das zu prüfende Recht. Lokal gibt es diese Überprüfung ebenfalls, sieht dann so aus ->
Bildschirmfoto 2018-05-03 um 08.50.38.png

und das Problem war eben, dass er dieses decode des Tokens etliche 100 male aufgerufen hat.
 
Zuletzt bearbeitet:
JWT ist per se keine Verschlüsselung, sondern eine kryptografisch signierter Datensatz mit ein paar Spielregeln.
Die eigentlichen Daten liegen jedoch als base64 codierter JSON-Text quasi lesbar vor.

Über dieses Objekt wird ein Message Authentication Code (MAC) erzeugt, welcher kryptografisch signiert ist.
Dadurch können Manipulationen an den Daten des Datensatzes quasi verhindert werden, weil die Signatur dann nicht mehr zu den Daten passt.
Aber bei eventuellen Lücken im JWT Stack, soll es halt schon gegeben haben, kann man die Daten halt eben doch manipulieren, um zum Beispiel seine Rechte auszuweiten. Bei komplett Clientseitigen Applikationen kann ich mir ja einen JWT-Stack einbauen, den ich benutzen möchte und nicht einen, den der Entwickler mal vorgesehen hat :)

Abgesehen davon:
Wo kommt das Token her? Wird das auch Clienseitig gebildet?
Hast du das Geheimnis (= das "Passwort") da irgendwo in den Client-Quelltext eingebaut? Oder hast du ein authentification & authorisatien Backend aufgebaut an dem sich die User per SSO (Domänen Netzwerk via NTLM oder LDAP oder so z.B.) anmelden und dann ihr Token zurückgeliefert bekommen?

Falls das Geheimnis irgendwo im Client-Quelltext mit drinnen steckt, kannst du dir die Mühe mit den Krypto quasi sparen.
Dann ist das JWT nur noch ein "rumfummel Schutz" aber wenn euch da jemand etwas böses will, dann hat er alle Materialien und Werkzeuge an einen Ort zusammen:= Clusterfuck.

Ausnahme: Du würdest public private key Krypto verwenden, das geht auch mit JWT. Aber dein verwendetes "HMAC SHA256" ist ein SHA2 Hashwert, der mittels AES im JWT geschützt wird. Damit hast du den Klassiker im Krypto: Das Schlüsselverteilungsproblem. Deswegen gibt es ja ein Schlüsselaustauschprotokoll, das ist aber nur mit einer asymmetrischen Verschlüsselung zu erreichen und nicht mit einer symmetrischen wie AES eine ist. Und der private key dürfte natürlich ebenfalls nicht im Client zur Entschlüsselung dienen. Die validierung oder falsifizierung MUSS zwigend im Backend stattfinden. JWT ist ja eigentlich dazu gedacht REST APIs abzusichern und keine kompletten Client-Frontends.

Ansonsten: Trenne mal dein Token an den zwei Punkten auf und jage das durch ein Base64 decoder oder Kopiere das Token einfach mal bei jwt.io in die Toolbox ;)

Hoffe ausreichend zur Verwirrung beigetragen zu haben.
PS: Bitte nicht falsch verstehen: JWT sind klasse. Besser als das sonstige "API Key" Gelumpe. Aber die Integration von Krypto in einer Applikation bedarf einiges an Gehirnakrobatik ;)
 
Zuletzt bearbeitet:
@sitis: Nicht den Localstorage dafür benutzen! Sonst wird deine Seite anfällig für XSS Angriffe.

Das Prozedere sollte einfach so ablaufen:

1. User öffnet deine Angular App
2. User sieht das Login Formular
3. User gibt Username und Passwort ein und drückt Enter
4. Server überprüft, ob die Daten valide sind, falls ja:
5. Server erzeugt JWT (und signiert es dabei) und Refresh Token
6. Server schickt die Token an den Client
7. Der Client speichert die Token in irgendeiner JavaScript Variable bzw. in irgend einem Angular Service
8. Fertig

In Schritt 7 hast du die Möglichkeit, um alle Daten für spätere Zugriffe vorzubereiten. Dort extrahierst du einfach deine Rechte und speicherst sie einfach als Array irgendwo in deinem Service ab.

Jetzt weiß das Frontend welche Rechte der User hat. Das ist natürlich kein echtes "Wissen", weil diese Daten vom Benutzer manipuliert werden können (ist ja nur JavaScript im Browser). Aber gerade bei einer Single-Page-App hat man am Frontend keine Wahl: Man muss dem User und seinen im Frontend hinterlegten Daten glauben - zumindest für die Darstellung der Seite.
(Selbst wenn du Code einbaust, der die Rechte alle 5 Millisekunden neu überprüft, dann ist es immer noch sehr einfach diese "Sicherheit" auszuhebeln, weil sich der Frontend Code manipulieren lässt)

Optimalerweise solltest du deinen Service natürlich so reaktiv wie möglich aufbauen, sodass die gesamte Applikation direkt auf sämtliche Änderungen der Daten reagieren kann. Wenn der Code einfach genug ist, kann man absolut problemlos zehntausende Observables gleichzeitig observen. (In einer normalen App erreicht man aber meist gerade so 100 gleichzeitig).

Also quasi so:
Code:
class MyAuthService {
  jwtSubject = new BehaviorSubject(null);
  jwt$ = this.jwtSubject.asObservable();

  login(username, password) {
    this.jwtSubject.next(
      this.apiService.login(username, password).pipe(
        map(response -> ...) // hier das token aus der response extrahieren
        map(token -> MyJWTUtil.decode(token)) // dann das token decodieren
        map(jwt -> ...) // optional: die Daten aus dem JWT aufbereiten
      )
    );
  }

  logout() {
    // token "zerstören":
    this.jwtSubject.next(null);
  }

  isLoggedIn() {
    return this.jwt$.pipe(
      map(jwt -> ... !== null)
    );
  }

  hasRight(right) {
    return this.jwt$.pipe(
      map(jwt -> ...) // hier die rights extrahieren
      map(rights -> rights.includes(right))
    );
  }

}
(ich habe das jetzt so aus dem Kopf geschrieben. Also keine Garantie für syntaktische Korrektheit)

Sobald das Backend aufgerufen wird, wird dann jeweils das Token mitgeschickt und das Backend stellt sicher, dass der Nutzer seine Aktion auch wirklich ausführen darf.

Für mehr Sicherheit, sollte man die Lebenszeit des Tokens auf wenige Minuten begrenzen. Und dann alle paar Minuten mittels Refresh Token, das JWT erneuern. Wenn man das nicht macht, kann folgendes passieren:
1. User loggt sich ein (erhält ein ewig gültiges JWT)
2. User baut Unfug
3. User wird vom Admin gesperrt
4. Das JWT vom User ändert sich dadurch logischerweise nicht
5. Sowohl Frontend als auch Backend sehen nur das JWT und sehen, dass es valide ist und lassen den User weiter machen
6. Der User baut weiterhin Unfug

Wenn nun das Token aber nur n Minuten gültig ist und man es dann gezwungenermaßen erneuern muss, dann weiß man sehr genau wie lang es dauert, bis der User wirklich gesperrt ist: max. n Minuten.
 
Zuletzt bearbeitet:
Vielen Dank für Euer ausführliches Feedback! :-)

Ich habe mich vermutlich etwas missverständlich ausgedrückt. Das Token wird aktuell schon auf dem Server generiert und dann an den User zurückgesendet. Das Secret liegt ebenfalls in einer config Datei auf dem Server und nicht beim Client. Das ganze übernimmt der authService. Der kümmert sich um login / logout etc.

Um dieses Problem mit dem "User baut Mist und muss gesperrt werden" zu umgehen, hab ich eine kleine "Krücke" gebaut. Wenn ich als Admin im Rechtedialog einen User sperre, wird in der Datenbank ein hasToRelog key auf true gesetzt. Dieser Key wird bei jedem Routenwechsel geprüft und sollte hier ein true zurückkommen, das token gelöscht, der localStorage gecleared und der User mit einem Hinweis auf den Loginbildschirm redirected.

Ich bin noch ziemlich neu in dem ganzen Angular Thema, muss mich da erstmal reinfummeln weshalb ich mit den ganzen Infos von Euch echt viel anfangen kann - danke! :-)
 
Dein Zusammenbau klingt nach einem verkrüppelten Hybriden :D

Eigentlich solltest du nur mit dem Backend kommunizieren, wenn es nötig ist. Ein Routenwechsel hat nichts mit dem Backend zu tun. Und deine "Krücke" zerstört den Nutzen von JWT. Du hast damit mehr oder weniger eine datenbank-basierte HTTP Session erschaffen, nur dass dein Token jetzt zusätzlich noch Daten enthält und dadurch (unnötig) lang wird.
Der große Vorteil eines signierten JWT ist ja gerade, dass man sich den Datenbankzugriff (bzw. Kommunikation mit dem Token Server) sparen kann. (vor allem interessant für Microservices). Nennt sich "stateless auth".
Du hast also eine eigenartige Mischung aus Stateful Session und Stateless JWT Auth zusammengebaut.

Der User hat volle Kontrolle über den Frontend Code. D.h. der Code zum automatisierten Löschen des Tokens im Browser ist wertlos. Das kann ein versierter Angreifer in ein paar Sekunden unterbinden.

Und zum LocalStorage: Schau mal bei Google nach "xss localstorage jwt". Diese Kombination ist nur in ganz bestimmten Fällen "sicher". Einfacher ist es komplett auf den LocalStorage zu verzichten. Du kannst alles in deinen Angular Services speichern.
 
Das Signieren des Tokens heißt für mich jetzt, dass das Token auf dem Server generiert und dann an den User zurückübermittelt wird. Lokal kann ich es dennoch ganz normal dekodieren, aber wenn ein User an dem dekodierten Token Änderungen vornimmt, würde der Server das Token ablehnen, weil es nicht mehr zu dem signierten (auf dem Server gespeicherten!?) Token passt?

Haha, eine hybride, verkrüppelte Krücke :D! Na, ich bin froh, dass ich das überhaupt alles so hinbekommen habe. Aber an den Stellen, an denen es optimierungsbedarf gibt, setz ich gerne an und arbeite nach. Das mit den Tokens schaue ich mir definitiv noch mal an, da hab ich auf jeden Fall einiges begriffen jetzt!
 
Dann hast du das noch nicht ganz richtig verstanden.

1. Server erstellt den Inhalt (= payload) des Tokens. (also UserId, Ablaufdatum, etc.)
2. Der Server signiert diesen Payload mit seinem Key. (diesen Key kennt NUR der Auth Server, sonst könnte ja jeder valide Token erstellen).
3. Der Server schickt das JWT an den Client (JWT setzt sich zusammen aus: Definition des Signatur-Algorithmus, Payload im Klartext, Signatur des Payloads).

Auf dem Server wird rein gar nichts gespeichert.

Der Client (= Frontend) kann jetzt einfach den Payload auslesen und verwenden und sich darauf verlassen, dass der Inhalt gültig ist. Das ist natürlich keine Garantie für valide Daten, aber das ist bei einer Single-Page-App eh irrelevant, weil der Frontend Code so oder so manipuliert werden kann.

Wenn der Server einen Request vom Client erhält, dann ist im Request das Token enthalten.
Der Server nimmt dieses Token und erstellt wieder die Signatur (exakt so wie in Schritt 2 oben).
Und wenn die neu erstellte Signatur mit der aus dem Token übereinstimmt, dann ist das Token gültig.

Das ist das übliche / einfache (symmetrische) Verfahren. (Hier kann die Signatur theoretisch auch eine verschlüsselte Form des Payloads sein. Das ist nicht so wichtig. Das einzig Wichtige ist, dass NUR der Server die Signatur erstellen kann. Wenn das sichergestellt ist, kann jeder am Token rumfummeln wie er will, aber keiner wird eine gültige Signatur dafür erstellen können. Heißt: Der Server wird jedes mal sagen "Du komms hier nüsch rein!")

---

Dann gibt es noch ein anderes (asymmetrisches) Verfahren mit zusätzlichem Public Key.
Hierbei signiert der Server das Token mit seinem Private Key. Und jeder der den Public Key hat (den darf jeder haben, ist ja schließlich "public"), kann die Gültigkeit des Tokens überprüfen. Das ist das bevorzugte Verfahren für MicroServices, kann aber auch in kleinen Projekten benutzt werden. Der zusätzliche Public Key ist der einzige Mehraufwand.

---

Sobald du das Token auf dem Server speicherst (ob Arbeitsspeicher oder Datenbank ist egal), hast du "stateful auth". Dann kannst quasi genau so gut eine normale HTTP Session und Cookies benutzen. Das hat dann natürlich wieder andere potenzielle Risiken mit denen du dich rumschlagen darfst ;)

---

Die einzige "Gefahr" bei JWTs ist, dass jemand den Key vom Server knackt. Dann kann diese Person ihre eigenen gültigen JWTs erstellen (natürlich mit gültiger Signatur) und an den Server schicken. Deshalb kann man die Sicherheit noch weiter erhöhen indem man z.B. täglich neue Keys für die Signatur generiert.
Das Knacken eines 0815-Keys braucht aber auf aktuellen Serverfarmen mehrere Jahre. Soll heißen: Ein normaler User, dem 10-20 Computer zur Verfügung stehen, wird das in seiner Lebenszeit nicht schaffen. Wenn du also keine Terroranschläge planst oder Atomkraftwerke betreibst, kannst du also im Prinzip drauf verzichten :D Aber auch, wenn du diese zusätzliche Sicherheit einbauen willst, kannst du das machen. Das ist eine Sache von höchstens 1-2 Stunden.
 
Zuletzt bearbeitet:
Microservices vom Typ "REST API" leben ganz gut mit dem symmetrischen Verfahren, da das Geheimnis im Backend bleibt, was man als Entwickler alleine unter Kontrolle hat (haben sollte) und demnach auch das Schlüsselverteilungsproblem nicht besteht.

Oftmals ist das ja so, dass es einen Endpunkt im Service gibt, an dem sich ein User mit seinen Credentials anmeldet. Entweder via oAuth2.0 SSO oder irgend einen "Benutzernamen / Passwort / OTP"-Tinnef. Manchmal auch mittels eines generierten API-Keys, welcher irgendwo an anderer Stelle aus dem System gefallen ist.

Dieser Auth-Endpunkt, so nenne ich ihn jetzt mal, liefert dann ein (signiertes) JWT an den "Client" zurück, welches für alle anderen Aufrufe an der API genutzt werden muss.
Der Vorteil dabei ist, dass dieses Token, anders als ein simpler API-Key, halt diese eingebauten Scopes (gültig für) und Laufzeiten und Lebenszeiten hat usw. und man so, REST-Konform (stateless) Authentifikation (Benutzer) und Autorisation (Rechte) abbilden kann.
Mittels eines API-Keys bekommt man nur eine Authentifikation (Benutzer) abgebildet und muss jedesmal die Autorisation im Backend prüfen, was teilweise gefährlich (Multi Key Using, uvm.) und teilweise falsch, und eigentlich immer unperformant sein kann.

Das ist jedoch nicht als server side user sessions gedacht und auch nicht dafür geeignet eine user session an einer Webapplikation zu steuern.
 
Zuletzt bearbeitet:
Wow, erneut vielen Dank für die Ausführungen, das hat dann Licht ins Dunkel gebracht! :)

Ich hab das secret von "yoursecret" jetzt mal abgeändert... denn wenn einer einen Wörterbuch Angriff drauf loslaufen lässt, dürfte das der erste versuch direkt nach admin und 000 sein ;-)

Vielen vielen Dank!
 
Zuletzt bearbeitet:
Dann hast du wohl das übliche / einfache symmetrische HMAC Verfahren am laufen. (steht ja im Header deines Tokens, welches Verfahren du benutzt. Also HS256 oder so)
Dabei wird die Signatur aus einer verschlüsselten Form des Payloads erstellt. Hier gilt für die Sicherheit dasselbe wie für Passwörter: Möglichst lang und möglichst zufällig.

Knacken lässt sich sowas am Einfachsten per Wörterbuch Angriff. Und ansonsten bleibt halt Bruteforce ;)
 
Interessant wie man sich so entwickelt... vor ein paar Wochen war es noch Bildschirmfoto 2018-05-03 um 14.58.36.png und mittlerweile

Bildschirmfoto 2018-05-03 um 15.01.31.png

vielleicht gibts da ja auch noch optimierungsansätze? :)
 
Was macht der Code `passport.authenticate('jwt', {session:false})`?

In deinem Authorization Header sollte `Bearer` stehen und nicht `JWT`.

Deine `decoded` Variable wird im falschen Scope deklariert. Die sollte vor dem `if(req.headers ...)` deklariert werden. Die Variable wird ja auch schließlich nach dem `if`-Block wieder benutzt.

`UserRights.findById` klingt irgendwie nicht logisch. Da geht's ja nicht um IDs, oder?

Die HTTP Codes sind auch nicht unbedingt korrekt. Nicht alles ist 401 ;) An machen Stellen passt 400 oder 403 besser.

Und der gesamte `if(req.headers ...) { ... }` Block sollte in eine eigene Funktion ausgelagert werden. Den exakt selben Code musst du ja bei jedem Request ausführen. Und aktuell musst du die 10 Zeilen jedes mal kopieren.

Das sind alles nur Kleinigkeiten, hat viel mit Code Style zu tun. Also für die eigentliche Funktion des Programms ist es natürlich nicht so wichtig, aber sobald man mit mehreren Leuten im Team arbeitet ist es sau praktisch. Dafür gibt's schließlich Standards ;)

In meinen Projekten versuche ich Texte und Sätze im Backend komplett zu vermeiden. Hat aber eher was mit Internationalisierung und verschiedenen Ausgabeformaten zu tun. Ich würde also einfach bei Erfolg also nur `success: true, code: 200` oder zurückgeben. Der Client ist dann dafür verantwortlich diese Codes in Sprache zu übersetzen.
Wenn du z.B. einen Mobile Client erstellst, dann ist dieser lange String vielleicht überhaupt nicht darstellbar. Und schon müsste man eine Weiche auf dem Backend einbauen, aber das Backend hat ja eigentlich mit der Darstellung überhaupt nichts am Hut. Das soll sich um die Verwaltung der Daten kümmern.
 
Zuletzt bearbeitet:
Zurück
Oben