Tworzę aplikację, która będzie obsługiwać wielu użytkowników. Chodzi o to, że nie jestem w stanie dowiedzieć się, jak uwierzytelnić klienta / użytkownika.
Tworzę aplikację, taką jak http://quickblox.com/, w której podam poświadczenia moim użytkownikom, którzy wykorzystają je do zbudowania aplikacji N , w których nie mogą podać swojej nazwy użytkownika i hasła w celu uwierzytelnienia.
Załóżmy, że idzie to w następujący sposób. (Podobnie jak QuickBlox)
1. Użytkownik tworzy konto w mojej witrynie.
2. Użytkownik może utworzyć N kluczy API i tajnych poświadczeń. (W przypadku wielu aplikacji)
3. Użytkownik użyje tych poświadczeń w swoich aplikacjach (Android, iOS, JavaScript itp.), Aby porozmawiać z moimi interfejsami API REST.
(Interfejsy API REST mają dostęp do odczytu i zapisu).
Moje obawy?
Użytkownicy umieszczą swoje poświadczenia (klucz API i klucz tajny) w tworzonych przez siebie aplikacjach, co jeśli ktoś zdobędzie te klucze i spróbuje naśladować użytkownika? (Dekompilując APK lub bezpośrednio patrząc na kod JavaScript.
Czy gdzieś się mylę?
Jestem zdezorientowany, aby zaprojektować ten trzypoziomowy mechanizm użytkownika.
Odpowiedzi:
Od kilku lat projektuję interfejsy API REST. Za bardzo się martwisz. Ostatnio inny użytkownik na tym forum zadał pytanie, gdzie martwił się przechowywaniem punktów końcowych URI w swoim kodzie JavaScript po stronie klienta .
Obowiązują te same zasady, co w przypadku programisty JavaScript. Jeśli zezwalasz osobom z zewnątrz na integrację interfejsu API, interfejs API ma taką samą widoczność jak zwykła witryna i powinieneś traktować go w ten sam sposób.
Cytat z oryginalnej odpowiedzi:
Należy zaprojektować tokeny dostępu do aplikacji, aby zezwalały tylko na operacje, które mają być dozwolone. Możesz mieć dwa rodzaje tokenów dostępu:
Ale co ktoś dekoduje kod źródłowy, usuwa tokeny z aplikacji, dowiaduje się, jakie są publiczne punkty końcowe i nadużywa twojej usługi internetowej?
Jeśli nie zarządzasz bezpośrednio aplikacjami korzystającymi z interfejsu API, nic tak naprawdę nie zabrania korzystania z interfejsu API w ten sam sposób bezpośrednio z aplikacji.
źródło
filtered data
(B) tylko swojego użytkownika . Czy jest teraz możliwe, czy istnieje jakieś obejście, aby uniemożliwić trzeciemu użytkownikowi kradzież wszystkich danych (A + B) mojego użytkownika . Czy ma sens?Twój problem jest nie tyle techniczny, co biznesowy.
Załóżmy, że masz interfejs API, który sprzedajesz swoim klientom (twórcom aplikacji) za zryczałtowaną stawkę 100 GBP rocznie, nieograniczony dostęp.
No cóż, oczywiście mogę kupić twoją usługę za 100 £ i sprzedać ją 10 osobom po 50 $ każda. Nie chcesz tego! więc starasz się wymyślić ograniczenie, które pozwoli ci sprzedawać API bez narażania się na arbitraż.
Jeśli ograniczysz tylko liczbę aplikacji, klient może utworzyć jedną aplikację, która akceptuje połączenia z innych aplikacji i przekazuje je dalej.
Jeśli ograniczysz użytkowników, ponownie klient może ukryć użytkowników za własnym uwierzytelnieniem i wyglądać na jednego użytkownika.
To, co musisz zrobić, to przekazać klientowi koszt każdego połączenia API. tj. opłata za połączenie API lub ustaw limit połączeń na rok.
To popycha ten sam problem arbitrażu na twoich klientów. Zmusza ich do wprowadzenia środków zapobiegających kradzieży kluczy przez użytkowników. W takim przypadku ukrywanie interfejsu API za interfejsem użytkownika uwierzytelnionego przez użytkownika.
źródło
Wszystkie pozostałe odpowiedzi wydają się sugerować, że problem przechowywania sekretu w aplikacji na urządzeniach konsumenckich nie jest możliwy do rozwiązania.
Jasne, że tak.
Dwie zasady (szczegóły implementacji zostaną spełnione):
Biorąc pod uwagę, że jeśli klient wysyła żądanie do punktu końcowego uwierzytelnianie z poświadczeniami, a uwierzytelnia it serwera, serwer może wygenerować dynamicznego tymczasowego tokenu (czas oparte tymczasowy znaczenia). Ten token powinien zostać zapamiętany w kliencie i wysłany z kolejnymi żądaniami.
Będziesz potrzebował mechanizmu okresowego „odświeżania” tokena, co oznacza, że dostaniesz nowy. Wystarczy zbudować punkt końcowy REST, który pozwala wygenerować nowy token z istniejącego, aby uniknąć konieczności ponownego uwierzytelnienia na podstawie poświadczeń.
Jeśli próbujesz uniknąć ponownego uwierzytelnienia użytkownika końcowego, uwierzytelnienie to może być początkową jednorazową konfiguracją aplikacji po jej zainstalowaniu.
To rozwiązanie po prostu pozwala uniknąć konieczności przechowywania statycznego tokena osadzonego w pliku binarnym aplikacji. Token jest generowany w locie przez serwer tylko w odpowiedzi na udane uwierzytelnienie. Aby złośliwy użytkownik mógł sprawdzić twoją aplikację i spróbować uzyskać nieautoryzowany dostęp do interfejsu API, musiałby się uwierzytelnić tak samo jak wszyscy inni.
źródło
Jeśli masz unikalne klucze dla aplikacji, możesz ich użyć tylko podczas początkowego uwierzytelniania połączenia, inicjowanego przez klienta, po czym przełączasz się na ciągły unikalny token uwierzytelniania dla aplikacji.
Twój serwer od czasu do czasu zmienia (rzuca) token dla każdej aplikacji klienckiej (na przykład okresowo plus / minus jakieś losowe rozmyte / losowe opóźnienie). Toczący się token jest znany tylko między serwerem a uwierzytelnionym klientem.
Nowe tokeny są zwracane przy pomocy zwykłych odpowiedzi. Ilekroć odpowiedź zawiera nowy token, aplikacja odbierająca musi przełączyć się na używanie go w kolejnych żądaniach.
Ilekroć wymiana z klientem nie jest zsynchronizowana (jakiś błąd protokołu), serwer zażąda ponownego uwierzytelnienia (poprzez odpowiedź błędu na następne żądanie klienta lub wspierany poprawną odpowiedzią na żądanie klienta dla przykład).
Wstępne uwierzytelnienie zainicjowane przez klientów, gdy aktywny token jest aktywnie używany, należy traktować podejrzliwie - może to być próba naśladowania. Pozwoliłbym na to tylko wtedy, gdy wymiana stanie się bezczynna przez dłuższy czas niż oczekiwano, co może być na przykład spowodowane przez awarię / restart klienta z nową instancją, która nie ma ruchomego tokena.
Byłoby jeszcze lepiej zachować token po stronie klienta, aby zrestartowany klient mógł kontynuować od miejsca, w którym pozostawił go poprzednik - znacznie zawężając możliwości naśladowania.
Taki schemat spowodowałby, że naśladowanie byłoby co najmniej dość trudne - klient naśladujący musiałby dokładnie przewidzieć okno, kiedy autoryzowany klient przestanie wysyłać żądania na tyle długo, aby serwer mógł stwierdzić, czy akceptacja nowego klienta przy użyciu określonego klucza może mieć miejsce. Takie żądania poza dozwolonym oknem mogą być wykorzystane jako wykrycie prób naśladowania i być może zainicjować pewne środki zaradcze (czarna lista IP itp.).
źródło
Z tego co wiem, to co wspomniałeś, to jedyny sposób, aby to zrobić. Aplikacja przechowująca klucz z pewnością stanowi ryzyko, ale istnieją różne sposoby jego obejścia. Zawsze możesz użyć magazynu kluczy do przechowywania klucza, niż na stałe, co wymusza jednorazowe logowanie.
Powinieneś również rozważyć powiązanie klucza z klientem, dlatego jeśli ktoś naśladuje, powinieneś mieć warstwę bezpieczeństwa, aby sprawdzić klienta, klucz i agenty użytkownika, aby natychmiast zablokować żądanie. Poproś o przypadek użycia w celu ponownego wydania lub ponownego upewnienia się, że klucze nie zostały naśladowane.
źródło
Jeśli zależysz od przekazania tokenów autoryzacyjnych klientom w celu zainstalowania ich aplikacji, teoretycznie zawsze będzie możliwe, aby ktoś dokonał inżynierii wstecznej aplikacji i wyodrębnił je. Aby temu zapobiec, potrzebujesz mechanizmu, który nie wymagałby tajności w aplikacji klienckiej. To trudne. Mogę jednak zasugerować kilka opcji do przemyślenia.
Masz problem po wydaniu poświadczeń, nie masz kontroli nad tym, jak bezpiecznie są one przechowywane. Ponadto, jeśli wymagasz od użytkownika przesłania poświadczeń, ktoś może MITM połączyć twoje połączenie i ukraść tokeny bezpośrednio, nie zawracając sobie głowy inżynierią wsteczną aplikacji.
Jednym ze sposobów utrudnienia wyodrębnienia tokena autoryzacji jest zaciemnienie go. To po prostu podnosi poprzeczkę, ale nie uniemożliwia, a aby to zrobić, musiałbyś zachować kontrolę nad tajemnicą. Możesz wdrożyć bibliotekę, która zawiera tajne informacje i jest specyficzna dla każdego klienta. Możesz użyć biblioteki do komunikowania się ze swoimi serwerami i może nawet nie będziesz musiał podawać użytkownikowi tajnych informacji, może to być po prostu osadzone w bibliotece. Nie rozwiązuje to problemu inżynierii wstecznej twojej biblioteki, ale daje ci kontrolę nad poziomem zaciemnienia. Wadą jest to, że gdy jedna osoba złamie zaciemnianie w bibliotece, może zaatakować dowolną twoją bibliotekę, chyba że napiszesz kod, który znacznie różni każdą bibliotekę. To wprowadza własny zestaw problemów.
To może nieco odbiegać od zakresu twojego pytania, ale jest związane z bezpieczeństwem twojego tokena, więc o tym wspomnę. Aby zapobiec trywialnej kradzieży tokena przez drut, prawdopodobnie nie chcesz wysyłać tokena bezpośrednio, zamiast tego możesz podpisywać ruch za pomocą funkcji HMAC. Możesz sprawdzić poprawność komunikatu, obliczając HMAC komunikatu na serwerze i porównując go z HMAC wysłanym od klienta. Używałbyś tokena jako klucza do funkcji HMAC, więc tylko osoba znająca token może podpisywać ruch. Jest to lepsze dla bezpieczeństwa twojego tokena, ponieważ nigdy nie wysyłasz go bezpośrednio na serwer, aby nie mógł zostać przechwycony i skradziony bezpośrednio. Aby uzyskać więcej informacji na temat HMACS, zobacz to pytanie: /security/20129/how-and-when-do-i-use-hmac/20301
Żadne rozwiązanie zabezpieczające nie będzie niemożliwe do zdobycia, musisz zdecydować, ile będzie ono kosztowało wdrożenie w porównaniu do prawdopodobieństwa i kosztu naruszenia.
źródło
Cytując siebie:
To trochę sprzeczność, prawda? ;)
Jak powiedzieli inni, nie możesz. Jeśli aplikacja korzysta z klucza API, można go zdekompilować tak, jak chcesz uzyskać klucz (klucze) i użyć go.
Poza wymaganiem dodatkowego prawidłowego uwierzytelnienia użytkownika, możesz jedynie ograniczyć szkody:
źródło