Jeśli zawsze zastanawiałeś się, jak działa i jak stworzyć aplikację opartą o OpenID Connect … to dobrze trafiłeś. W artykule opisuję właśnie Quarkus OpenID Connect z Auth0. Miłej lektury!
Krótko o OpenID Connect
OpenID Connect 1.0, jak możemy przeczytać w specyfikacji, jest zbiorem rozwiązań pozwalających na identyfikację użytkowników końcowych na podstawie ich uwierzytelnienia dokonanego w serwerze autoryzacyjnym. Cały szkielet oparty jest na standardzie OAuth 2.0.
Jako, że niniejszy artykuł nie jest poświęcony OpenID Connect, to tutaj tylko mały zarys działania rozwiązania.
W tym przypadku zależy nam, żeby nasza aplikacja korzystała z zewnętrznego systemu do uwierzytelnienia klientów. Tym zewnętrznym systemem będzie Auth0.
Użytkownik, który będzie chciał skorzystać z naszej aplikacji, zostanie przekierowany w celu uwierzytelnienia właśnie do Auth0. Oznacza to, że dzięki wykorzystani OpenID Connect możemy wydelegować operację uwierzytelnienia do zewnętrznej usługi.
Auth0 na podstawie danych dostarczonych przez użytkownika dokonuje uwierzytelnienia, a następnie zwraca tzw. Authorization Code do naszej aplikacji. Dzięki temu aplikacja będzie mogła uzyskać w kolejnych żądaniach ID Token oraz Access Token.
Access Token jest poświadczeniem mówiącym o zdolności dostępu do zasobów.
ID Token z kolei zawiera tzw. claims, czyli oświadczenia dotyczące danego uwierzytelnienia. Zawartość tego token zdefiniowana jest bardzo szczegółowo w specyfikacji. Znajdują się w nim m. in. o podmiocie uwierzytelnienia (w przypadku Auth0 jest to unikalny identyfikator użytkownika), wystawcy tokenu, dacie ważności, etc.
W artykule skupiamy się właśnie na ID Token, gdyż chcemy uzyskać informację o użytkowniku.
Auth0
Ze względu na bardzo dobre wrażenia z komercyjnego zastosowania (i bardzo szybkiego złożenie konfiguracji), chciałbym skorzystać z Auth0.
Auth0 jest bardzo fajnym rozwiązaniem dostępnym w chmurze. Zastosowanie platformy załatwia nam szereg czynności, które musielibyśmy wykonać ręcznie, żeby udostępnić usługę tego typu samodzielnie.
Po założeniu darmowego konta konfiguracja jest bardzo prosta. Jak widać na rysunku poniżej.
Ważną częścią konfiguracji jest poprawne zdefiniowane callbacku. Callback jest adresem URL, na który zostanie przekierowany użytkownik po poprawnym uwierzytelnieniu.
Użytkowników naszej aplikacji możemy z kolei dodawać na podstronie Users & Roles.
Quarkus i OpenID Connect
Jeśli popatrzymy na stronę https://code.quarkus.io/ to dowiemy się, że rozszerzenie dotyczące OpenID Connect (OIDC) jest jeszcze w fazie Preview.
I rzeczywiście pierwsze zetknięcie się z tym rozszerzeniem daje wrażenie, że nie jest to jeszcze w pełni gotowe rozwiązanie.
Przede wszystkim możemy trafić na dwa artykuły:
- QUARKUS – USING OPENID CONNECT ADAPTER TO PROTECT JAX-RS APPLICATIONS
- QUARKUS – PROTECTING WEB APPLICATIONS USING OPENID CONNECT
Oba niestety korzystają z Keyclock jako usługi zarządzania tożsamością. Nie jest to oczywiście dziwne, bo wiemy, że i za Quarkusem i za Keyclock stoi Red Hat.
Ja bym jednak chciał skorzystać z Auth0. Pojawił się jednak pewien problem …
Quarkus i Auth0 – czy to będzie działać od razu?
Kiedy zaczynałem pisać ten artykuł Quarkus był dostępny w wersji 1.2.1.Final. Odpowiedź na powyższe pytanie będzie więc musiała być nieco bardziej szczegółowa. Zatem – tak, ale będzie wymagana niewielka modyfikacja zależności.
...
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
<exclusions>
<exclusion>
<groupId>io.vertx</groupId>
<artifactId>vertx-auth-oauth2</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-auth-oauth2</artifactId>
<version>3.8.5</version>
</dependency>
...
Dlaczego wymieniamy bibliotekę vertx-auth-oauth2 z wersji 3.8.4 na 3.8.5?
Powód jest dosyć zaskakujący. Chodzi o zwykłe porównywanie adresów URL we właściwości quarkus.oidc.auth-server-url. Czyli właściwości definiującej adres naszego serwera autoryzacji Auth0. A wszystko to ze względu na to, że Quarkus deleguje tę operację do verx-auth-oauth2, gdzie pojawia się problem końca URL ze znakiem „/” i bez „/”. Wersja 3.8.5 poprawia tę sytuację, a o całym przypadku można poczytać tutaj Quarkus OIDC does not work with Auth0.
Teraz, kiedy kończę pisać ten artykuł, jest czwartek, 19 marca. I dzisiaj wyszedł właśnie Quarkus w wersji 1.3.0.Final. Nowa wersja korzysta już z vertx-auth-oauth2 3.8.5. Co za tym idzie, odpowiedź na pytanie z nagłówka w chwili obecnej to – tak.
Konfiguracja Quarkus OIDC
Konfiguracja przedstawia się następująco:
quarkus.oidc.auth-server-url=https://itbrains.auth0.com
quarkus.oidc.authentication.redirect-path=/
quarkus.oidc.application-type=web-app
quarkus.oidc.client-id=TMWyZEVfKSYJBKnQz368Hm83yAlBl29a
quarkus.oidc.credentials.secret=XXX
quarkus.oidc.authentication.scopes=email
quarkus.http.auth.permission.authenticated.paths=/*
quarkus.http.auth.permission.authenticated.policy=authenticated
Przede wszystkim ustawiamy właściwości na podstawie danych naszej aplikacji w Auth0.
Oczywiście quarkus.oidc.credentials.secret pozostaje tajne, bo to za pomocą tego hasła będzie odbywała się komunikacja między naszą aplikacją (klientem), a serwerem autoryzacji.
Wartość web-app właściwości quarkus.oidc.application-type wskazuje Quarkusowi, że będziemy wykorzystywać Authorization Code Flow z OpenID Connect.
Chcielibyśmy również dodać email do zakresu danych, stąd w ten sposób ustawiamy właściwość quarkus.oidc.authentication.scopes.
ID Token
Po poprawnym uwierzytelnieniu nasza aplikacja pobierze w tle ID Token. Token ten możemy wstrzyknąć do naszego zasobu. Quarkus rozpozna tę sytuację automatycznie.
@Path("/")
public class SecuredResource {
@Inject
@IdToken
JsonWebToken idToken;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
String subject = idToken.getSubject();
String email = idToken.getClaim("email");
return "Secured. Subject: " + subject + " with email: " + email;
}
}
Z tokenu pobieramy podmiot, który został uwierzytelniony. Jest to identyfikator użytkownika na platformie Auth0. Pobieramy również poświadczenie (ang. claim), o które poprosiliśmy definiując zakres danych tokenu (ang. scope).
Ostatnie poprawki
Ze względu na to, że chcemy, aby SecuredResource obsługiwało ścieżkę „/” musimy usunąć plik index.html z naszego projektu. Dla przypomnienia – znajduje się on w nietypowym katalogu META-INF/resources.
Jeśli byśmy tego nie zrobili, to Quarkus automatycznie wyświetlałby domyślną stronę zamiast naszego tekstu z danymi z ID Token.
Wynik końcowy
Uruchamiamy aplikację za pomocą:
mvn quarkus:dev
W przeglądarce wchodzimy na stronę http://localhost:8080/, która przekierowuje nas od razu do logowania w Auth0.
Po poprawny zalogowaniu sterowanie ponownie wraca do naszej aplikacji. ID Token zostaje wstrzyknięty do naszej klasy. Wybrane dane w nim zawarte pojawią się w tekście na ekranie:
W pasku adresu przeglądarki będziemy również widzieć wartość Authorization Code oraz state, które służą do weryfikacji oraz komunikacji aplikacji z Auth0.
Podsumowanie
Stale rosnąca popularność OpenID Connect wśród klientów korporacyjnych sprawia, że wiedza płynąca z artykułu będzie mogła być wykorzystana całkiem szybko.
Jeśli podoba Ci się taki format artykułów, daj mi znać 🔥🔥🔥
Zapisz się na newsletter lub skontaktuj się ze mną przez jeden z kanałów wymienionych na stronie Poznaj mnie.
Miłego weekendu!
Kod do niniejszego artykułu znajdziesz tutaj:
https://github.com/bchmielewski/quarkus-oidc-auth0