Projektowanie uwierzytelniania dla interfejsu API REST

11

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:

  1. Klient i serwer są w .NET4 (część klienta w profilu klienta)
  2. Serwer udostępnia za pomocą usługi WCF REST
  3. 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:

  1. Zanim klient podejmie próbę uwierzytelnienia, generuje parę kluczy Diffie-Hellman przy użyciu ECDiffieHellmanCngklasy.
  2. Wysyła publiczną część pary kluczy przewodowo wraz z nazwą użytkownika i hasłem (oczywiście przez HTTPS).
  3. Serwer uwierzytelnia kombinację nazwy użytkownika i hasła, jeśli się powiedzie, wykonuje następujące czynności:
    1. Tworzy unikalny token sesji
    2. Generuje własną parę kluczy DH i oblicz wspólny klucz tajny na podstawie klucza publicznego dostarczonego przez klienta
    3. 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)
    4. Zwraca token sesji, jego publiczny klucz DH i komunikat o powodzeniu uwierzytelnienia
  4. 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ć?

Matt Sieker
źródło
Nie rozumiem, w jaki sposób generowanie kluczy DH w ogóle zwiększa bezpieczeństwo w porównaniu do zwykłego używania HTTPS wszędzie i używania zwykłego starego pliku cookie sesji. Przy prawidłowym użyciu HTTPS chroni już przed atakami typu man-in-the-middle i replay.
Lie Ryan,

Odpowiedzi:

5

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ę.

S.Lott
źródło
Hmm, to nie wygląda źle, jedna rzecz, która uniemożliwia mi użycie go w tym przypadku: Jesteśmy sklepem .Net. Plus, nie ma wiele o używaniu go po stronie serwera WCF. Jeden nie spamujący link, który mogłem znaleźć w Google na ten temat, wskazuje na używanie WIF i WS-Federation.
Matt Sieker
1
@Matt Sieker: „Nie musisz używać ich komponentów”. Przeczytaj o ich API zamiast wymyślać własne.
S.Lott,
Ach, myślę, że rozumiem, co masz na myśli, wymagania dotyczące oddzwaniania. To ciekawe, mógłbym przyjrzeć się temu bardziej, gdyby nie ten projekt, dla przyszłych. Zamiast robić uwierzytelnianie jako jeden fragment atomowy, podziel go nieco, aby serwer mógł kontrolować to, czego potrzebuje od klienta ...
Matt Sieker
Na początku wprowadziliśmy własne, ale kilka lat temu przeszliśmy do OpenAM w IG Group. Bardzo zadowolony z produktu open source.
Robert Morschel,
2

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

codingoutloud
źródło