Pytanie to zostało poruszone w nieco innej formie, tutaj:
RESTful Authentication
Ale to rozwiązuje to po stronie serwera. Spójrzmy na to od strony klienta. Zanim to jednak zrobimy, istnieje ważne preludium:
JavaScript Crypto jest beznadziejny
Artykuł Matasano na ten temat jest znany, ale zawarte w nim lekcje są dość ważne:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-consanted-harmful/
Podsumowując:
- Atak typu man-in-the-middle może w prosty sposób zastąpić Twój kod kryptograficzny
<script>
function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
- Atak typu man-in-the-middle jest trywialny wobec strony, która obsługuje dowolny zasób przez połączenie inne niż SSL.
- Gdy masz już SSL, i tak używasz prawdziwego szyfrowania.
I aby dodać własny wniosek:
- Pomyślny atak XSS może spowodować, że osoba atakująca wykona kod w przeglądarce klienta, nawet jeśli używasz protokołu SSL - więc nawet jeśli walczysz o każdy właz, szyfrowanie przeglądarki może nadal zawieść, jeśli atakujący znajdzie sposób na wykonanie dowolny kod javascript w przeglądarce innej osoby.
To sprawia, że wiele schematów uwierzytelniania RESTful jest niemożliwych lub niemądrych, jeśli zamierzasz używać klienta JavaScript. Spójrzmy!
Podstawowe uwierzytelnianie HTTP
Przede wszystkim uwierzytelnianie podstawowe HTTP. Najprostszy schemat: wystarczy podać nazwę i hasło przy każdym żądaniu.
To oczywiście wymaga protokołu SSL, ponieważ przekazujesz nazwę i hasło zakodowane w Base64 (odwracalnie) przy każdym żądaniu. Każdy, kto słucha przez linię, może w prosty sposób wyodrębnić nazwę użytkownika i hasło. Większość argumentów „Autoryzacja podstawowa jest niepewna” pochodzi z miejsca „Autoryzacja podstawowa przez HTTP”, co jest okropnym pomysłem.
Przeglądarka zapewnia wbudowaną obsługę uwierzytelniania podstawowego HTTP, ale jest brzydka jak grzech i prawdopodobnie nie należy jej używać w swojej aplikacji. Alternatywą jest jednak przechowywanie nazwy użytkownika i hasła w JavaScript.
To jest najbardziej RESTful rozwiązanie. Serwer nie wymaga żadnej wiedzy o stanie i uwierzytelnia każdą indywidualną interakcję z użytkownikiem. Niektórzy entuzjaści REST (głównie słowianie) twierdzą, że utrzymywanie dowolnego stanu jest herezją i będą pienieć na ustach, jeśli pomyślisz o jakiejkolwiek innej metodzie uwierzytelnienia. Istnieją teoretyczne korzyści z tego rodzaju zgodności ze standardami - jest obsługiwany przez Apache po wyjęciu z pudełka - możesz przechowywać swoje obiekty jako pliki w folderach chronionych plikami .htaccess, jeśli chcesz.
Problemem ? Buforujesz po stronie klienta nazwę użytkownika i hasło. Daje to evil.ru lepszy efekt - nawet najbardziej podstawowa słabość XSS może spowodować, że klient przesyła swoją nazwę użytkownika i hasło na zły serwer. Możesz spróbować zmniejszyć to ryzyko, mieszając i soląc hasło, ale pamiętaj: JavaScript Crypto jest beznadziejny . Możesz zmniejszyć to ryzyko, pozostawiając je do obsługi podstawowego uwierzytelniania przeglądarki, ale ... brzydkie jak grzech, jak wspomniano wcześniej.
HTTP Digest Auth
Czy możliwe jest uwierzytelnianie Digest w jQuery?
Bardziej „bezpieczne” uwierzytelnianie, jest to wyzwanie mieszania żądania / odpowiedzi. Z wyjątkiem JavaScript Crypto jest beznadziejny , więc działa tylko przez SSL i nadal musisz buforować nazwę użytkownika i hasło po stronie klienta, co czyni go bardziej skomplikowanym niż HTTP Basic Auth, ale nie jest bardziej bezpieczny .
Uwierzytelnianie zapytania z dodatkowymi parametrami podpisu.
Kolejne bardziej „bezpieczne” uwierzytelnianie, w którym szyfrujesz parametry za pomocą danych nonce i timing (w celu ochrony przed atakami powtarzającymi się i timing) i wysyłasz. Jednym z najlepszych przykładów tego jest protokół OAuth 1.0, który, o ile mi wiadomo, jest dość ciekawym sposobem na wdrożenie uwierzytelnienia na serwerze REST.
http://tools.ietf.org/html/rfc5849
Och, ale nie ma żadnych klientów OAuth 1.0 dla JavaScript. Dlaczego?
JavaScript Crypto jest beznadziejna , pamiętaj. JavaScript nie może uczestniczyć w OAuth 1.0 bez protokołu SSL, a nadal musisz przechowywać nazwę użytkownika i hasło klienta lokalnie - co stawia tę kategorię jako uwierzytelnianie szyfrowane - jest bardziej skomplikowane niż uwierzytelnianie podstawowe HTTP, ale nie jest bardziej bezpieczne .
Znak
Użytkownik wysyła nazwę użytkownika i hasło, aw zamian otrzymuje token, którego można użyć do uwierzytelnienia żądań.
Jest to nieznacznie bezpieczniejsze niż uwierzytelnianie podstawowe HTTP, ponieważ po zakończeniu transakcji nazwa użytkownika / hasło możesz odrzucić wrażliwe dane. Jest również mniej RESTful, ponieważ tokeny stanowią „stan” i komplikują implementację serwera.
SSL wciąż
Pociesz się jednak, że nadal musisz wysłać tę początkową nazwę użytkownika i hasło, aby otrzymać token. Wrażliwe informacje nadal dotykają Twojego skompromitowanego JavaScript.
Aby chronić dane uwierzytelniające użytkownika, nadal musisz powstrzymywać atakujących przed JavaScript, a także przesyłać nazwę użytkownika i hasło przez sieć. Wymagany SSL.
Wygaśnięcie tokena
Często egzekwowane są zasady dotyczące tokenów, takie jak „hej, gdy ten token jest za długi, odrzuć go i ponownie uwierzytelnij użytkownika”. lub „Jestem pewien, że jedynym adresem IP, który może używać tego tokena, jest XXX.XXX.XXX.XXX
”. Wiele z tych zasad to całkiem dobre pomysły.
Ogień
Jednak użycie tokena Bez protokołu SSL jest nadal podatne na atak o nazwie „sidejacking”: http://codebutler.github.io/firesheep/
Atakujący nie uzyskuje poświadczeń użytkownika, ale nadal może udawać, że jest użytkownikiem, co może być dość złe.
tl; dr: Wysyłanie niezaszyfrowanych tokenów przez sieć oznacza, że atakujący mogą łatwo zdobyć te tokeny i udawać, że są użytkownikiem. FireSheep to program, który sprawia, że jest to bardzo łatwe.
Oddzielna, bezpieczniejsza strefa
Im większa aplikacja, którą uruchamiasz, tym trudniej jest absolutnie upewnić się, że nie będą w stanie wstrzyknąć kodu, który zmieni sposób przetwarzania wrażliwych danych. Czy całkowicie ufasz swojemu CDN? Twoi reklamodawcy? Twoja własna baza kodu?
Wspólne dla danych karty kredytowej, a rzadziej dla nazwy użytkownika i hasła - niektórzy realizatorzy przechowują „poufne dane” na innej stronie niż reszta aplikacji, strona, którą można ściśle kontrolować i zablokować najlepiej, jak to możliwe, najlepiej taką, która jest trudny do wyłudzenia użytkowników.
Cookie (oznacza po prostu Token)
Możliwe jest (i często) umieszczanie tokena uwierzytelniającego w pliku cookie. Nie zmienia to żadnych właściwości uwierzytelniania za pomocą tokena, jest to raczej wygoda. Wszystkie poprzednie argumenty nadal obowiązują.
Sesja (wciąż oznacza tylko Token)
Session Auth to po prostu uwierzytelnianie tokena, ale z kilkoma różnicami, które sprawiają, że wygląda to nieco inaczej:
- Użytkownicy rozpoczynają od nieuwierzytelnionego tokena.
- Backend utrzymuje obiekt „state”, który jest powiązany z tokenem użytkownika.
- Token znajduje się w pliku cookie.
- Środowisko aplikacji oddziela szczegóły od Ciebie.
Poza tym tak naprawdę nie różni się niczym od Token Auth.
Wędruje to jeszcze dalej od implementacji RESTful - z obiektami stanu idziesz dalej i dalej ścieżką zwykłego RPC na stanowym serwerze.
OAuth 2.0
OAuth 2.0 analizuje problem: „W jaki sposób oprogramowanie A zapewnia oprogramowaniu B dostęp do danych użytkownika X bez konieczności posiadania przez oprogramowanie B dostępu do danych logowania użytkownika X”.
Implementacja jest bardzo standardowym sposobem dla użytkownika, aby uzyskać token, a następnie dla usługi innej firmy, aby przejść „tak, ten użytkownik i ten token pasują, a teraz możesz uzyskać od nas niektóre ich dane”.
Zasadniczo jednak OAuth 2.0 to tylko protokół tokena. Wykazuje te same właściwości, co inne protokoły tokenów - nadal potrzebujesz SSL do ochrony tych tokenów - po prostu zmienia sposób ich generowania.
Są dwa sposoby, w jakie OAuth 2.0 może ci pomóc:
- Udzielanie uwierzytelnienia / informacji innym osobom
- Uzyskiwanie uwierzytelnienia / informacji od innych
Ale jeśli chodzi o to, po prostu ... używasz tokenów.
Powrót do twojego pytania
Pytanie, które zadajesz, brzmi: „czy powinienem przechowywać mój token w pliku cookie i pozwolić, aby automatyczne zarządzanie sesjami w moim środowisku zadbało o szczegóły, czy też powinienem przechowywać mój token w JavaScript i sam z nimi obchodzić?”
Odpowiedź brzmi: rób wszystko, co czyni cię szczęśliwym .
Jednak automatyczne zarządzanie sesjami polega na tym, że za kulisami dzieje się wiele magii. Często lepiej jest samemu kontrolować te szczegóły.
Mam 21 lat, więc SSL to tak
Inna odpowiedź brzmi: użyj https do wszystkiego, a bandyci ukradną hasła i tokeny użytkowników.