Przegląd
Chcę utworzyć interfejs API (REST) dla mojej aplikacji. Początkowym / głównym celem będzie konsumpcja przez aplikacje mobilne (iPhone, Android, Symbian itp.). Badałem różne mechanizmy uwierzytelniania i autoryzacji internetowych interfejsów API (badając inne implementacje). Mam głowę wokół większości podstawowych koncepcji, ale wciąż szukam wskazówek w kilku obszarach. Ostatnią rzeczą, którą chcę zrobić, jest wynalezienie koła, ale nie znajduję żadnych standardowych rozwiązań, które pasowałyby do moich kryteriów (jednak moje kryteria mogą być błędne, więc nie krępuj się również krytykować). Ponadto chcę, aby interfejs API był taki sam dla wszystkich platform / aplikacji, które go wykorzystują.
oAuth
Przejdę dalej i wyrzucę swój sprzeciw wobec oAuth, ponieważ wiem, że prawdopodobnie będzie to pierwsze oferowane rozwiązanie. W przypadku aplikacji mobilnych (a dokładniej aplikacji niebędących aplikacjami internetowymi) opuszczanie aplikacji (aby przejść do przeglądarki internetowej) w celu uwierzytelnienia wydaje się niewłaściwe. Ponadto, nie ma (jestem tego świadom) sposobu, aby przeglądarka zwróciła wywołanie zwrotne do aplikacji (szczególnie na wielu platformach). Znam kilka aplikacji, które to robią, ale po prostu źle się czuję i daje przerwę w UX aplikacji.
Wymagania
- Użytkownik wprowadza nazwę użytkownika / hasło do aplikacji.
- Każde wywołanie interfejsu API jest identyfikowane przez aplikację wywołującą.
- Koszty ogólne są ograniczone do minimum, a aspekt autoryzacji jest intuicyjny dla programistów.
- Mechanizm jest bezpieczny zarówno dla użytkownika końcowego (dane logowania nie są ujawnione), jak i programisty (dane logowania aplikacji nie są ujawnione).
- Jeśli to możliwe, nie wymagaj https (w żadnym wypadku nie jest to trudne wymaganie).
Moje obecne przemyślenia na temat wdrażania
Zewnętrzny programista poprosi o konto API. Otrzymają apikey i apisecret. Każde żądanie wymaga co najmniej trzech parametrów.
- apikey - podany deweloperowi przy rejestracji
- timestamp - podwaja się jako unikalny identyfikator każdej wiadomości dla danego apikey
- hash - skrót mieszania znacznika czasu + apisecret
Apikey jest wymagany do zidentyfikowania aplikacji wydającej żądanie. Znacznik czasu działa podobnie do oauth_nonce i unika / łagodzi ataki powtórki. Hash zapewnia, że żądanie zostało faktycznie wydane przez właściciela danego apikey.
W przypadku żądań uwierzytelnionych (wykonanych w imieniu użytkownika) nadal nie jestem zdecydowany, czy pójść z trasą tokenu dostępu lub kombinacją nazwy użytkownika i hasła. Tak czy inaczej, w pewnym momencie wymagane będzie połączenie nazwy użytkownika / hasła. Kiedy tak się stanie, zostanie użyty skrót kilku informacji (apikey, apisecret, timestamp) + hasło. Chciałbym poznać opinie na ten temat. Do Twojej wiadomości, najpierw musieliby hashować hasło, ponieważ nie przechowuję haseł w moim systemie bez mieszania.
Wniosek
Do Twojej wiadomości, nie jest to prośba o to, jak zbudować / ustrukturyzować API w ogóle, tylko jak obsługiwać uwierzytelnianie i autoryzację wyłącznie z poziomu aplikacji.
Losowe przemyślenia / pytania bonusowe
W przypadku interfejsów API, które wymagają tylko apikey jako części żądania, w jaki sposób można uniemożliwić komuś innemu niż właściciel apikey zobaczenie apikey (od momentu wysłania go w postaci jawnej) i wysyłanie nadmiernych próśb o przekroczenie limitów użycia? Może po prostu zastanawiam się nad tym, ale czy nie powinno być czegoś, co mogłoby potwierdzić, że prośba została zweryfikowana przez apikey właściciela? W moim przypadku taki był apisecret, nigdy nie jest pokazywany / przesyłany bez mieszania.
Mówiąc o hashach, co powiesz na md5 vs hmac-sha1? Czy to naprawdę ma znaczenie, gdy wszystkie wartości są mieszane z wystarczająco długimi danymi (np. Apisecret)?
Wcześniej zastanawiałem się nad dodaniem soli na użytkownika / wiersz do skrótu hasła moich użytkowników. Gdybym miał to zrobić, w jaki sposób aplikacja mogłaby utworzyć pasujący skrót, nie znając użytej soli?
Odpowiedzi:
Sposób, w jaki myślę o logowaniu się w moich projektach, to:
przed zalogowaniem użytkownik żąda
login_token
od serwera. Są one generowane i przechowywane na serwerze na żądanie i prawdopodobnie mają ograniczony okres użytkowania.aby się zalogować, aplikacja oblicza skrót hasła użytkownika, następnie haszy hasło hasłem,
login_token
aby uzyskać wartość, a następnie zwraca zarównologin_token
skrót, jak i skrót.Serwer sprawdza
login_token
, czy został wygenerowany, usuwając go z listy prawidłowychlogin_token
adresów. Serwer następnie łączy swój zapisany skrót hasła użytkownika zlogin_token
i zapewnia, że pasuje on do przesłanego połączonego tokena. Jeśli jest zgodny, uwierzytelniłeś użytkownika.Zaletą tego jest to, że nigdy nie przechowujesz hasła użytkownika na serwerze, hasło nigdy nie jest przekazywane jawnie, hash hasła jest przekazywany tylko podczas tworzenia konta (chociaż mogą istnieć sposoby na obejście tego), i powinno być bezpieczne przed atakami powtórkowymi, ponieważ
login_token
są usuwane z bazy danych przy użyciu.źródło
To mnóstwo pytań w jednym, myślę, że sporo osób nie udało się przeczytać do końca :)
Moje doświadczenie z uwierzytelnianiem usług sieciowych polega na tym, że ludzie zwykle go prześcigają, a problemy są takie same, jak na stronie internetowej. Możliwe bardzo proste opcje obejmują https dla kroku logowania, zwrot tokena, wymagają włączenia go do przyszłych żądań. Możesz również użyć podstawowego uwierzytelniania HTTP i po prostu przekazać rzeczy w nagłówku. Aby zwiększyć bezpieczeństwo, często obracaj / wygasaj tokeny, sprawdź, czy żądania przychodzą z tego samego bloku IP (może to być bałagan, gdy użytkownicy mobilni przemieszczają się między komórkami), połącz z kluczem API lub podobnym. Alternatywnie wykonaj krok oauth w kroku „klucz żądania” (ktoś zasugerował to już w poprzedniej odpowiedzi i jest to dobry pomysł) przed uwierzytelnieniem użytkownika i użyj go jako klucza wymaganego do wygenerowania tokena dostępu.
Alternatywą, z której jeszcze nie korzystałem, ale słyszałem wiele jako przyjazną dla urządzenia alternatywę dla oAuth, jest xAuth . Spójrz na to, a jeśli go użyjesz, będę bardzo zainteresowany, aby dowiedzieć się, jakie są twoje wrażenia.
Jeśli chodzi o haszowanie, sha1 jest nieco lepszy, ale nie rozłączaj się przy tym - cokolwiek urządzenia mogą łatwo (i szybko pod względem wydajności) wdrożyć, jest prawdopodobnie w porządku.
Mam nadzieję, że to pomoże, powodzenia :)
źródło
Czy szukasz mechanizmu uwierzytelniania po stronie serwera, który będzie obsługiwał aspekty uwierzytelniania i autoryzacji aplikacji mobilnej?
Zakładając, że tak jest, podszedłbym do tego w następujący sposób (ale tylko dlatego, że jestem programistą Java, więc facet z C # zrobiłby to inaczej):
Usługa uwierzytelniania i autoryzacji RESTful
Biblioteka / aplikacja bezpieczeństwa po stronie klienta
Więc teraz, kiedy widok z 30 000 stóp jest kompletny, jak sobie radzisz? Cóż, nie jest trudno stworzyć system uwierzytelniania i autoryzacji oparty na wymienionych technologiach po stronie serwera za pomocą klienta przeglądarki. W połączeniu z HTTPS frameworki zapewnią bezpieczny proces oparty na wspólnym tokenie (zwykle prezentowanym jako plik cookie) generowanym przez proces uwierzytelniania i używanym, gdy użytkownik chce coś zrobić. Ten token jest prezentowany przez klienta serwerowi za każdym razem, gdy ma miejsce jakiekolwiek żądanie.
W przypadku lokalnej aplikacji mobilnej wydaje się, że szukasz rozwiązania, które:
Cokolwiek robisz, nie próbuj wymyślać własnego protokołu bezpieczeństwa ani nie używaj zabezpieczeń przez zaciemnienie. Nigdy nie będziesz w stanie napisać lepszego algorytmu niż te, które są obecnie dostępne i bezpłatne. Ponadto ludzie ufają dobrze znanym algorytmom. Jeśli więc powiesz, że twoja biblioteka zabezpieczeń zapewnia autoryzację i uwierzytelnianie dla lokalnych aplikacji mobilnych przy użyciu kombinacji SSL, HTTPS, SpringSecurity i tokenów szyfrowanych AES, natychmiast zyskasz wiarygodność na rynku.
Mam nadzieję, że to pomoże i powodzenia w przedsięwzięciu. Jeśli chcesz uzyskać więcej informacji, daj mi znać - napisałem sporo aplikacji internetowych opartych na Spring Security, listach ACL i tym podobnych.
źródło
Twitter rozwiązał problem aplikacji zewnętrznej w oAuth, obsługując wariant, który nazywają xAuth . Niestety istnieje już wiele innych programów o tej nazwie, więc uporządkowanie może być mylące.
Protokół ma wartość oAuth, z tym wyjątkiem, że pomija fazę tokena żądania i po prostu natychmiast wydaje parę tokenów dostępu po otrzymaniu nazwy użytkownika i hasła. (Począwszy od kroku E tutaj .) Ta inicjał żądanie i odpowiedź muszą być zabezpieczone- wysyła nazwę użytkownika i hasło w postaci zwykłego tekstu oraz odbiera token dostępu i tajny token. Po skonfigurowaniu pary tokenów dostępu to, czy początkowa wymiana tokenów odbywała się za pomocą modelu oAuth, czy modelu xAuth, nie ma znaczenia zarówno dla klienta, jak i serwera przez resztę sesji. Ma to tę zaletę, że można wykorzystać istniejącą infrastrukturę oAuth i mieć prawie taką samą implementację dla aplikacji mobilnych / internetowych / stacjonarnych. Główną wadą jest to, że aplikacja ma dostęp do nazwy użytkownika i hasła klienta, ale wygląda na to, że twoje wymagania wymagają takiego podejścia.
W każdym razie chciałbym się zgodzić z twoją intuicją i intuicją kilku innych użytkowników: nie próbuj budować czegoś nowego od podstaw. Protokoły bezpieczeństwa mogą być łatwe do uruchomienia, ale zawsze są trudne do wykonania, a im bardziej skomplikowane, tym mniej prawdopodobne jest, że Twoi zewnętrzni programiści będą w stanie wdrożyć się przeciwko nim. Twój hipotetyczny protokół jest bardzo podobny do o (x) Auth - api_key / api_secret, nonce, sha1 hashed - ale zamiast być w stanie korzystać z jednej z wielu istniejących bibliotek, twoi programiści będą musieli stworzyć własne.
źródło
Bardzo późno na imprezę, ale chciałem dodać kilka dodatkowych punktów do rozważenia dla wszystkich zainteresowanych tym problemem. Pracuję dla firmy wykonującej rozwiązania bezpieczeństwa API mobilnych ( APVOV ), więc cały ten obszar jest zdecydowanie zgodny z moimi zainteresowaniami.
Na początek najważniejszą rzeczą do rozważenia przy zabezpieczaniu mobilnego interfejsu API jest to, ile jest ono warte . Właściwe rozwiązanie dla banku różni się od właściwego rozwiązania dla kogoś, kto po prostu robi rzeczy dla zabawy.
W proponowanym rozwiązaniu wspominasz, że wymagane będą co najmniej trzy parametry:
Oznacza to, że dla niektórych wywołań API nie jest wymagana nazwa użytkownika / hasło. Może to być przydatne w aplikacjach, w których nie chcesz wymuszać logowania (na przykład przeglądanie w sklepach internetowych).
Jest to nieco inny problem niż uwierzytelnianie użytkownika i bardziej przypomina uwierzytelnianie lub poświadczanie oprogramowania. Nie ma użytkownika, ale nadal chcesz się upewnić, że nie ma złośliwego dostępu do twojego API. Dlatego używasz swojego tajnego interfejsu API do podpisywania ruchu i identyfikowania kodu dostępu do interfejsu API jako autentycznego. Potencjalny problem z tym rozwiązaniem polega na tym, że musisz zdradzić sekret w każdej wersji aplikacji. Jeśli ktoś może wydobyć sekret, może użyć interfejsu API, podszywając się pod oprogramowanie, ale robiąc, co chce.
Aby przeciwdziałać temu zagrożeniu, możesz zrobić wiele rzeczy, w zależności od tego, jak cenne są dane. Zaciemnianie jest prostym sposobem na utrudnienie wydobycia sekretu. Istnieją narzędzia, które zrobią to za Ciebie, zwłaszcza w przypadku Androida, ale nadal musisz mieć kod, który generuje Twój skrót, a odpowiednio wykwalifikowana osoba zawsze może po prostu wywołać funkcję, która wykonuje skrót bezpośrednio.
Innym sposobem na ograniczenie nadmiernego użycia interfejsu API, który nie wymaga logowania, jest ograniczenie ruchu oraz potencjalna identyfikacja i blokowanie podejrzanych adresów IP. Ilość pracy, którą chcesz podjąć, będzie w dużej mierze zależeć od tego, jak wartościowe są twoje dane.
Poza tym możesz łatwo zacząć wchodzić w domenę mojej codziennej pracy. W każdym razie jest to kolejny aspekt zabezpieczania interfejsów API, który moim zdaniem jest ważny i chciał się zgłosić.
źródło