Pracuję nad interfejsem API dla usługi REST, którą zamierzam zarówno produkować, jak i konsumować. Ostatnie kilka dni spędziłem, próbując wymyślić, jak ładnie obsługiwać uwierzytelnianie, i myślę, że w końcu coś wymyśliłem.
Wymyślam to na podstawie następujących faktów na temat stosu aplikacji:
- Klient i serwer są w .NET4 (część klienta w profilu klienta)
- Serwer udostępnia za pomocą usługi WCF REST
- Naprawdę nie chcę przechowywać nazwy użytkownika i hasła w pamięci aplikacji
Od 3 chciałem użyć formy uwierzytelniania tokena, aby po zweryfikowaniu poświadczeń przez serwer klient otrzymał token z powrotem do użycia w pozostałej części aplikacji (pozwoli mi to robić inne rzeczy, takie jak przekroczenie limitu czasu użytkowników, możliwość płynnego przenoszenia użytkowników między wersjami internetowymi i komputerowymi itp.). Po zastanowieniu się, jak sprawić, by połączenia były odtwarzane ponownie i były odporne na manipulacje, wymyśliłem następujące rzeczy:
- Zanim klient podejmie próbę uwierzytelnienia, generuje parę kluczy Diffie-Hellman przy użyciu
ECDiffieHellmanCng
klasy. - Wysyła publiczną część pary kluczy przewodowo wraz z nazwą użytkownika i hasłem (oczywiście przez HTTPS).
- Serwer uwierzytelnia kombinację nazwy użytkownika i hasła, jeśli się powiedzie, wykonuje następujące czynności:
- Tworzy unikalny token sesji
- Generuje własną parę kluczy DH i oblicz wspólny klucz tajny na podstawie klucza publicznego dostarczonego przez klienta
- Odnotowuje w swojej bazie danych token sesji, wspólny klucz tajny, użytkownika i czas „ostatniej akcji” (używany w przypadku ruchomego okna wygaśnięcia)
- Zwraca token sesji, jego publiczny klucz DH i komunikat o powodzeniu uwierzytelnienia
- Klient bierze klucz DH z odpowiedzi, oblicza wspólny klucz tajny i przechowuje zarówno token, jak i klucz tajny w pamięci.
Od tego momentu kombinacja token / sekret sesji działa jak większość innych interfejsów API REST, z żądaniem odczytywanym odciskiem palca i znacznikiem czasu, a następnie generowanym przez niego HMAC. Za każdym razem, gdy klient wykonuje akcję przeciwko serwerowi, sprawdza parę token / klucz tajny i zezwala na akcję, jeśli jest ważna i nie wygasła, i aktualizuje ostatni rekord akcji w sesji.
Nie widzę żadnych oczywistych wad i prawdopodobnie jestem w tym celu przeprojektowany, ale w pewnym momencie muszę się tego nauczyć. HMAC zapobiega atakom powtórkowym, negocjacje DH pomagają zapobiegać atakom MITM (nie mogę sobie wyobrazić wykonalnego ataku z góry mojej głowy między HMAC / DH).
Jakieś dziury, które każdy może w to wbić?
źródło
Odpowiedzi:
Zamiast wymyślać własne, powinieneś rozważyć przeczytanie API OpenAM i pożyczenie go.
http://forgerock.com/openam.html
Wiki OpenAM jest szczególnie pomocne
https://wikis.forgerock.org/confluence/display/openam/Home
Nie musisz używać ich komponentów. Ale jeśli użyjesz ich API, przekonasz się, że twoje życie będzie prostsze na dłuższą metę.
źródło
Zgadzam się w 100% z @ S.Lott, że nie chcesz tworzyć własnych. Sugeruję spojrzenie na inną alternatywę: usługę kontroli dostępu do systemu Windows Azure (ACS). ACS kosztuje pieniądze, ale jest bardzo tani (10 000 transakcji za 0,01 USD) i obsługiwana jest spora infrastruktura. WIF działa na kliencie.
Jest to również rozwiązanie oparte na standardach / roszczeniach - co jest modne. Sprawdź ten artykuł na temat korzystania z WCF, REST i ACS razem .
Jeśli myślisz o przyszłości, jest to również mechanizm, który może rosnąć wraz z tobą - ponieważ masz aplikacje mobilne poza zaporą, partnerami i tak dalej. Nawet jeśli nie chcesz go używać, ponieważ dodaje zależności poza zaporą, możesz sprawdzić, czy nie ma pomysłów. Bardzo zręczny.
Powodzenia! -Rachunek
źródło