Błąd logowania RESTful: Zwróć 401 lub odpowiedź niestandardową

103

To jest pytanie koncepcyjne.

Mam aplikację kliencką (mobilną), która musi obsługiwać akcję logowania do usługi sieciowej RESTful. Ponieważ usługa sieciowa jest zgodna z REST, oznacza to, że klient akceptuje nazwę użytkownika / hasło od użytkownika, weryfikuje tę nazwę użytkownika / hasło w usłudze, a następnie po prostu pamięta o wysyłaniu tej nazwy użytkownika / hasła przy wszystkich kolejnych żądaniach.

Wszystkie inne odpowiedzi w tej usłudze internetowej są dostarczane w formacie JSON.

Pytanie brzmi, kiedy wysyłam zapytanie do usługi sieciowej, aby po prostu dowiedzieć się, czy podana nazwa użytkownika / hasło są prawidłowe, czy usługa sieciowa powinna zawsze odpowiadać danymi JSON informującymi mnie o pomyślnym lub nieudanym wyniku, czy też powinna zwrócić HTTP 200 przy dobrych poświadczeniach i HTTP 401 na złych poświadczeniach.

Powodem, dla którego pytam, jest to, że niektóre inne usługi RESTful używają 401 dla złych poświadczeń, nawet gdy pytasz tylko, czy poświadczenia są prawidłowe. Jednak rozumiem, że odpowiedzi 401 są takie, że reprezentują one zasoby, do których nie powinieneś mieć dostępu bez ważnych poświadczeń. Jednak zasób logowania POWINIEN być dostępny dla każdego, ponieważ jedynym celem zasobu logowania jest poinformowanie Cię, czy Twoje poświadczenia są ważne.

Innymi słowy, wydaje mi się, że taka prośba:

myservice.com/this/is/a/user/action 

powinien zwrócić 401, jeśli podano nieprawidłowe poświadczenia. Ale prośba taka jak:

myservice.com/are/these/credentials/valid

nigdy nie powinien zwracać 401, ponieważ ten konkretny adres URL (żądanie) jest autoryzowany z ważnymi poświadczeniami lub bez nich.

Chciałbym usłyszeć kilka uzasadnionych opinii w tej czy innej sprawie. Jaki jest standardowy sposób radzenia sobie z tym i czy standardowy sposób postępowania jest logicznie odpowiedni?

Matt
źródło

Odpowiedzi:

128

Po pierwsze. 401 to poprawny kod odpowiedzi do wysłania w przypadku niepowodzenia logowania.

401 Unauthorized Podobny do 403 Zabroniony, ale specjalnie do użycia, gdy uwierzytelnianie jest wymagane i nie powiodło się lub nie zostało jeszcze dostarczone. Odpowiedź musi zawierać pole nagłówka WWW-Authenticate zawierające wezwanie mające zastosowanie do żądanego zasobu.

Twoje zamieszanie na temat myservice.com/are/these/credentials/valid odsyłaniem 401, gdy po prostu robisz czek, jest oparte na fakcie, że wykonywanie żądań logicznych w REST często jest błędne z powodu ograniczeń RESTful. Każde żądanie powinno zwrócić zasób. Zadawanie pytań logicznych w usłudze RESTful to śliski spadek do RPC.

Teraz nie wiem, jak zachowują się usługi, na które patrzyłeś. Ale dobrym sposobem rozwiązania tego problemu jest posiadanie czegoś w rodzaju obiektu Konto, który próbujesz uzyskać. Jeśli twoje dane uwierzytelniające są poprawne, otrzymasz obiekt Account, jeśli nie chcesz marnować przepustowości tylko na „sprawdzenie”, możesz wykonać HEAD na tym samym zasobie.

Obiekt konta jest również dobrym miejscem do przechowywania wszystkich tych nieznośnych wartości logicznych, dla których w innym przypadku trudno byłoby utworzyć indywidualne zasoby.

Duchowny
źródło
2
Twój punkt widzenia dotyczący zwrotu zasobów wydaje się słuszny i być może jest to właściwy krok. Jeśli chodzi o stwierdzenie, że 401 jest właściwą odpowiedzią, byłbym wdzięczny za wyjaśnienie. Przeczytałem specyfikację HTTP, tak jak tu zawarłeś, ale nie jest to dla mnie bezpośrednie i oczywiste potwierdzenie twojego twierdzenia. Mianowicie, uwierzytelnianie NIE jest wymagane, aby zapytać o ważność poświadczeń - jednak to, co dołączyłeś, mówi „specjalnie do użycia, gdy wymagane jest uwierzytelnienie”.
Matt
3
Twój sposób patrzenia na to jest poprawny. Nie musisz być uwierzytelniany, aby móc poprosić o obiekt konta. Ale musisz pomyślnie uwierzytelnić się, aby móc odebrać zasób, i to tam, gdzie authentication is required and has failed or has not yet been providedma to zastosowanie, ponieważ nie pytasz o ważność poświadczeń, ale o określony zasób na podstawie dostarczonych poświadczeń.
Cleric
2
Rozumiem, dlaczego chcesz wykonać „połączenie kontrolne” i dlatego nadal promowałbym 401 jako odpowiedni kod odpowiedzi na nieudane uwierzytelnienie, nawet jeśli połączenie nie wymaga uwierzytelnienia, aby można było wywołać. 204 No Content również może być odpowiednie, ale wydaje się nieco niejednoznaczne.
Cleric
4
Nie rozumiem, jak to może być poprawne, chyba że używasz uwierzytelniania podstawowego lub szyfrowanego. Zgodnie z cytowaną częścią specyfikacji: „Odpowiedź musi zawierać uwierzytelnianie WWW” - a jeśli odwołujesz się do sekcji 14.47: „Proces uwierzytelniania dostępu HTTP jest opisany w sekcji„ Uwierzytelnianie HTTP: uwierzytelnianie podstawowe i szyfrowane ”. dla mnie, że 401 nie jest odpowiednie, jeśli używasz typowego sprawdzania poprawności adresu e-mail / hasła.
Jonah
1
Myślę, że to może być złe, wdrażałem klientów zarówno w wersji internetowej, jak i mobilnej i przechwytuję 401, aby przekierować do ekranu logowania. Ale gdy ktoś jest już na ekranie logowania i poda błędne dane uwierzytelniające, odpowiedź ma również 401 i spróbuje ponownie przekierować. Powinien istnieć inny kod stanu dla nieudanej próby uwierzytelnienia podczas jawnej próby. Może złe żądanie lub nawet błąd serwera?
Japheth Ongeri - inkalimeva
27

401 należy wysłać tylko wtedy, gdy żądanie wymaga pola nagłówka autoryzacji i autoryzacja się nie powiedzie. Ponieważ interfejs API logowania nie wymaga autoryzacji, stąd 401 to moim zdaniem zły kod błędu

Zgodnie ze standardem tutaj https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

* 10.4.2 401 Brak autoryzacji

Żądanie wymaga uwierzytelnienia użytkownika. Odpowiedź MUSI zawierać nagłówek WWW-Authenticate (sekcja 14.47) zawierający wezwanie mające zastosowanie do żądanego zasobu. Klient MOŻE powtórzyć żądanie z odpowiednim nagłówkiem Authorization (rozdział 14.8). Jeśli żądanie zawierało już poświadczenia autoryzacji, odpowiedź 401 wskazuje, że odmówiono autoryzacji dla tych poświadczeń. Jeżeli odpowiedź 401 zawiera to samo wezwanie, co poprzednia odpowiedź, a agent użytkownika już co najmniej raz próbował uwierzytelnić, wówczas użytkownikowi POWINIEN zostać przedstawiona jednostka, która została podana w odpowiedzi, ponieważ jednostka ta może zawierać istotne informacje diagnostyczne. Uwierzytelnianie dostępu HTTP jest wyjaśnione w rozdziale „Uwierzytelnianie HTTP: uwierzytelnianie podstawowe i cyfrowe” [43]. *

vinksharma
źródło
8
Zgadzam się z tobą w tej sprawie, ale jaki jest alternatywny status odpowiedzi do wysłania? Wdrażałem klientów zarówno internetowych, jak i mobilnych i przechwytuję 401, aby przekierować do ekranu logowania. Ale kiedy ktoś jest już na ekranie logowania i poda błędne dane uwierzytelniające, odpowiedź również ma 401 i spróbuje ponownie przekierować ... co byś zrobił?
Japheth Ongeri - inkalimeva
0

Zwróć 409 z odpowiednim komunikatem o błędzie.

krewetka
źródło