Zmienny adres serwera uwierzytelniania

0

Flow jest nastęujący:

  1. Uderz do REST API bez tokenu JWT
  2. Odczytaj z nagłówków adres serwera uwierzytelniania
  3. Uwierzytelnij za pomocą OpenID - sposób client credentials
  4. Uderz do REST API już z tokenem JWT

W Springu samo pobieranie tokenu po uprzedniej konfiguracji wygląda tak:

https://docs.spring.io/spring-security/site/docs/5.2.12.RELEASE/reference/html/oauth2.html#using-the-access-token

Natomiast same wywołania REST API zewnętrznej usługi. Pierwszy pomysł to RestTemplate + opcjonalnie Feign. Na powyższej stronie jest przykład z WebClient, lecz aktualnie nie używam reaktywnego flow w aplikacji (tutaj chyba nie ma to znaczenia - można użyć WebClient).

Spring ma też słabo udokumentowany OAuth2RestTemplate.

Ale teraz pytanie:

  1. Czy użycie do tego Springa to dobry pomysł, czy użyć zewnętrznych bibliotek, które są bardziej intuicyjne?
  2. Czy da się zrobić to prościej (w Springu lub innymi bibliotekami)?
  3. Czy da się automatycznie obsłużyć odczytywanie URL serwera uwierzytelniania, czy trzeba obsłużyć to ręcznie?

Nie pisałem jeszcze klienta z użyciem OAuth i nie wiem, ile rzeczy Spring umie zrobić z automatu, a ile trzeba ręcznie pisać logiki.

Spring obsługuje też refresh tokeny, a czy sam je umie odświeżać, czy też robimy to ręcznie? Słabo to wszystko udokumentowane.

Jeśli trzeba to ręcznie obsłużyć, to może to być taki flow:

  1. Wykonaj żądanie (nieważne, czy mamy token, czy nie - jak mamy, to go dołączamy)
  2. Jeśli aplikacja zwróci 401, to powinniśmy dostać w nagłówku adres serwera uwierzytelniania
  3. Uwierzytelniamy się pod tym adresem sposobem client credentials (client ID + hasło)
  4. Jak dostaniemy token, to trzeba go gdzieś przechować (Spring ma do tego komponent)
  5. Uderzamy do API już z tokenem (czasami trzeba go będzie odświeżyć)
0

Wybór frameworka to jest szczegół. Jeśli w całym projekcie pożeniliście się ze springiem to kontynuuj.

0

Nie chodzi o sam framework, ale o biblioteki do uwierzytelniania. Na razie spróbuję to zrobić za pomocą Spring Security.

RestTemplate mają niedługo usunąć na rzecz WebClient. Kolejny moduł do dodania do pom.xml. Bardziej zależy mi na tym, żeby aplikacja nie rozrosła się zbytnio, bo na serwerze po odpaleniu wszystkich usług (w tym ElasticSearch) już mało RAM-u zostało. Ale patrząc naprzód, to lepiej używać tego, co będzie wspierane.

3
Shiba Inu napisał(a):
  1. Jeśli aplikacja zwróci 401, to powinniśmy dostać w nagłówku adres serwera uwierzytelniania

A dlaczego tak? Jeszcze chyba się nie spotkałem z taką implementacją ;)
Czemu adres serwera autoryzacyjnego miałby się zmieniać?

0

Ale o który z tych endpointów pytasz? Bo pisanie wszystkiego od początku samodzielnie to trochę bez sensu jest.

0
some_ONE napisał(a):

A dlaczego tak? Jeszcze chyba się nie spotkałem z taką implementacją ;)
Czemu adres serwera autoryzacyjnego miałby się zmieniać?

Taka jest teoria, a czy adres będzie się zmieniał, tego nie wiem. Można na razie założyć, że adres jest stały.

Jednak trzeba użyć metody Authorization Code with PKCE. Czyli aplikacja webowa SPA (Single Page Application) powinna uderzyć do serwera uwierzytelniania i sama uzyskać token, po czym przekazać go do serwera. Wydaje się, że lepiej będzie użyć Hybrid OAuth 2 w ten sposób, żeby aplikacja serwerowa uderzała po token.

W Springu jest za dużo magii. To, co chcę osiągnąć, to możliwość powiązania konta użytkownika z innymi aplikacjami podobnie jak na Facebooku. Czyli tokeny muszą być gdzieś przechowywane np. w bazie, a do tego muszą być odświeżane na podstawie refresh tokenu. Może ktoś ma przykłady, jak to poprawnie zaimplementować w Springu?

0

Czy to jest bezpieczne, że samo uwierzytelnianie w zewnętrznej usłudze odbędzie się po stronie przeglądarki, a następnie przekażemy ten access token na serwer?

Przepływ danych:

  1. Przeglądarka przekierowuje użytkownika do serwera uwierzytelniającego zewnętrznej usługi
  2. Użytkownik loguje się i wyraża zgodę na dostęp
  3. Przeglądarka uderza po access token
  4. Przeglądarka wysyła access token do serwera, który tym tokenem będzie pobierał dane z zewnętrznej usługi

Na ile to jest bezpieczne z punktu bezpieczeństwa? Teoretycznie za pomocą XSS atakujący może wykraść authorization_code z query string, uderzyć po token i uzyskać dostęp do danych wrażliwych. Może atak man-in-the-middle też da się przeprowadzić i wykraść token podczas wysyłania do serwera.

Czy jest jakaś różnica, jeśli to serwer uderzy po token (mając authorization_code), a nie przeglądarka?

Trudność w tym, że serwer rozpoznaje użytkownika po nagłówku Authorization, a jeśli zewnętrzna usługa po pomyślnym zalogowaniu i wyrażeniu zgód przekieruje na URL serwera (Java) zamiast do SPA (Angular), to nie będzie nagłówka Authorization. W ogóle serwer proxy nie przepuści żądania bez Authorization (można dodać wyjątki, ale lepiej tego uniknąć).

0
Shiba Inu napisał(a):

Na ile to jest bezpieczne z punktu bezpieczeństwa? Teoretycznie za pomocą XSS atakujący może wykraść authorization_code z query string, uderzyć po token i uzyskać dostęp do danych wrażliwych. Może atak man-in-the-middle też da się przeprowadzić i wykraść token podczas wysyłania do serwera.

No ja nie wiem, czy masz podatność XSS, albo endpointy podpisane lewymi certami.

Czy jest jakaś różnica, jeśli to serwer uderzy po token (mając authorization_code), a nie przeglądarka?

OAuth przewiduje kilka różnych flow, w zależności kto jest klientem. Teoretycznie nic nie stoi na przeszkodzie, żeby serwer działał tak samo jak SPA, ale zwykle stosuje się prostsze sposoby, bo w przeglądarce trzyma się tokeny "trochę zaufane", natomiast nad serwerem, przynajmniej w teorii powinieneś mieć pełną kontrolę i nie ma potrzeby aż tak tego komplikować.

Trudność w tym, że serwer rozpoznaje użytkownika po nagłówku Authorization, a jeśli zewnętrzna usługa po pomyślnym zalogowaniu i wyrażeniu zgód przekieruje na URL serwera (Java) zamiast do SPA (Angular), to nie będzie nagłówka Authorization. W ogóle serwer proxy nie przepuści żądania bez Authorization (można dodać wyjątki, ale lepiej tego uniknąć).

No i dlatego redirect_uri powinno wskazywać na twoje SPA, które powinno rozpoznać, zę w query params jest już idToken i odpowiednio zadziałać dalej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1