2017-04-19 13 views
5

Obecnie uczę się implementacji JWT z PHP i chcę używać tokenów JWT zamiast sesji dla mojej aplikacji RESTful.Czy bezpieczne jest przechowywanie poufnych danych w ładowności JWT?

Podczas tworzenia podpisu, robię coś w tym

token = base64Header + '.' + base64Payload + '.' + signature 

Tu są tylko za pomocą base64 ładunku. Jeśli wkleję w serwisach takich jak https://jwt.io/#debugger, ładunek zostanie odszyfrowany (nawet jeśli podpis jest nieprawidłowy).

na moje pytania,

  1. Czy JWT tylko do weryfikacji podpisu z serwera podczas wysyłania danych?
  2. Czy nie jest bezpieczne przechowywanie poufnych danych w usłudze Payload?
  3. Jeśli nie masz pewności, w jaki sposób zabezpieczyć ładunek?

Poniżej znajduje się przykładowy kod pisałem

<?php 
    $headers = base64_encode(json_encode([ 
     "typ" => "JWT", 
     "alg" => "HS256" 
    ])); 
    $claims = base64_encode(json_encode([ 
     "sub" => "1234567890", 
     "name" => "John Doe", 
     "admin" => true, 
     "jti" => "870a3de5-ea7b-4062-abef-11180e530f5a", 
     "iat" => 1492603378, 
     "exp" => 1492606978 
    ])); 
    $payload = $headers.".".$claims; 
    $signature = base64_encode(hash_hmac("sha256", $payload, 'secret', true)); 
    $encodedJWT = $payload.".".$signature; 
    // eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6Ijg3MGEzZGU1LWVhN2ItNDA2Mi1hYmVmLTExMTgwZTUzMGY1YSIsImlhdCI6MTQ5MjYwMzM3OCwiZXhwIjoxNDkyNjA2OTc4fQ.nvw-bAUgr7H_xr3q8_Yz8rCNtMohtn2YlCmcLoLBWlc 
+0

Prosimy uprzejmie przedstawić komentarze przed rezygnacją z głosowania. Uaktualnię moje pytanie, jeśli coś jest nie tak :) –

+0

Witam, na podstawie informacji z konferencji, w której uczestniczyłem w JWT, dane wrażliwe powinny pozostać w DB, a sam token powinien zawierać tylko informacje wymagane do szybkiej identyfikacji, a nie autoryzacji. – Auris

+0

Czy powinniśmy przekazać uwagi przed rezygnacją? - :) Powód, dla którego komentarze na dole strony są rzadkie, wynika z tego, że moderatorzy SO sugerują, że nie z powodu sporadycznych zemsty. – zaph

Odpowiedz

5

Gdybym wklej w miejscach takich jak https://jwt.io/#debugger, ładunek zostanie odszyfrowane (nawet jeśli podpis jest źle).

Osoby trzecie nie mogą zweryfikować podpisu, ponieważ nie mają tajnego klucza. Ładunek nie zostanie odszyfrowany - zostanie zdekodowany.

Idealnie powinieneś nie przechowywać wrażliwych danych w ładunku, ponieważ ładunek jest tylko kodowany base64 i nie jest szyfrowany. Oznacza to, że każdy, kto zdobędzie token, może przeglądać zawartość ładunku przez proste dekodowanie go przez base64.

Jeśli masz token w lokalnej pamięci przeglądarki, a Twoja witryna ma lukę XSS, kradzież tokena jest banalna. To wystarczająco źle, że atakujący ma ważną JWT (która, mam nadzieję, wkrótce niedługo wygaśnie), ale jeśli zawiera poufne dane, wtedy masz poważne kłopoty. Wyobraź sobie, że musisz powiadomić wszystkich użytkowników w swojej witrynie, że muszą teraz zmienić różne fragmenty poufnych danych o sobie ze względu na potencjalny masowy kompromis.

Zachowaj lekkość JWT. Przechowuj identyfikator użytkownika, jego role/granty w systemie. Jeśli chcesz dodać wrażliwe dane do ładunku, spróbuj ponownie przemyśleć rozwiązanie.

1

Jak rozumiem, próbujesz mieć kompletny serwer stateless, więc chcesz zachować nawet wrażliwe dane w tokenie.

Ale twój serwer nie może być całkowicie bezpaństwowcem. Ponieważ w celu wylogowania się, musisz mieć albo czarną listę lub białą listę w celu unieważnienia tokena. Dlatego w każdej prośbie musisz dotknąć bazy danych . Jeśli nie masz czarnej listy lub białej listy, tokeny są nadal poprawne, nawet jeśli użytkownik się wyloguje.

Lepiej więc uzyskać wrażliwe dane z bazy danych, ponieważ należy dotknąć bazy danych na każde żądanie.

+1

Posiadanie czarnej lub białej listy, jak mówisz, czyni ją mniej niż bezpaństwowcem. Dlatego należy tego unikać. Lepiej byłoby mieć po prostu krótkie żetony, więc nie ma akcji "wylogowania". Operacja wylogowania byłaby po prostu usunięciem tokena przez klienta. – jfadich

+0

Krótkie wygaśnięcie nie rozwiązuje problemu. Zwłaszcza w aplikacjach mobilnych, przynajmniej musisz mieć opcję, że użytkownik chce być zalogowany. (W nowoczesnych aplikacjach użytkownicy nigdy się nie wylogowują) Masz więc pewien rodzaj tokenów, które nie zawierają 'exp' w ogóle . Co jeśli użytkownik chce się wylogować? Token będzie ważny! –

+2

Posiadanie tokena bez "exp" jest bardzo złą praktyką. Znacznie lepiej byłoby mieć token uwierzytelniania i token odświeżania (tak działa większość produktów Google). Token autoryzacji jest wysyłany przy każdym żądaniu autoryzacji żądania, ale jest ważny tylko przez krótki czas (powiedzmy 30 minut). Odświeżający token służy do uzyskania nowego tokena autoryzacji po jego wygaśnięciu. Odświeżony token powinien nadal mieć wygaśnięcie, ale może być dłuższy (powiedzmy 2 tygodnie) i może zostać odświeżony. Aby się wylogować, klient usuwa oba tokeny. Dzięki temu użytkownicy zawsze będą się bezpiecznie logować (po prostu zachowaj tajemnicę świeżego tokena). – jfadich

1
  1. Czy JWT służy wyłącznie do weryfikacji podpisu z serwerem podczas wysyłania danych?

Nie, nie tylko podpisano JWT (JWS - RFC 7515), ale również zaszyfrowano JWT (JWE - RFC 7516).

  1. Czy nie jest bezpieczne przechowywanie poufnych danych w usłudze Payload?

Po zaszyfrowaniu JWT można bezpiecznie udostępniać poufne dane (chyba że naruszony zostanie algorytm lub klucz).

Ale w twoim przykładzie nie widzę wrażliwych danych, dlatego zastanawiam się, czy naprawdę ważne jest, aby używać JWE w twoim przypadku. Gorąco polecam read this blog post o JWT i sesjach i dlaczego nie powinieneś ich używać w tym celu (również spójrz na that part 2).

Jeśli naprawdę chcesz używać JWE, to napisałem a PHP library, który jest już w stanie załadować i stworzyć dowolny rodzaj Jose (JWS/JWE) i który obsługuje prawie wszystkie algorytmy z RFC 7518 po wyjęciu z pudełka. Inne biblioteki mogą istnieć, ale nie ma listy odnośników (https://jwt.io/ zawiera tylko wykazy implementacji JWS).