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?