W tym tekście przedstawiamy najważniejsze zmiany wprowadzone w najnowszych wersjach Keycloak oraz ich wpływ na proces migracji. Pokażemy także przykłady rozwiązywania typowych problemów, które pomogą przejść płynnie na nowsze wersje. Niezależnie od tego, czy chodzi o dostosowanie zaktualizowanych konfiguracji, czy zarządzanie wycofanymi funkcjami, ten artykuł dostarczy Ci praktycznych wskazówek, które usprawnią migrację Keycloak.
Migracja do dystrybucji Quarkus
Migracja do dystrybucji Quarkus była jednym z najbardziej wymagających procesów dla wielu użytkowników, szczególnie podczas aktualizacji do Keycloak 17, kiedy architektura zmieniła się z WildFly na framework Quarkus. Ta zmiana oznaczała odejście od tradycyjnego modelu serwera aplikacyjnego na rzecz nowoczesnego, lekkiego podejścia dostosowanego do Quarkusa. Konfiguracja Keycloak została całkowicie zmieniona – zamiast wdrażać aplikację na zewnętrznym serwerze aplikacyjnym, działa ona teraz jako samodzielna aplikacja, co znacząco upraszcza proces wdrażania.
Na przykład custom providers, które wcześniej było dynamicznie pakowane jako moduły dla WildFly, muszą obecnie zostać przebudowane i dostosowane, ponieważ środowisko wykonawcze (runtime) jest niezmienne. Wymaga to modyfikacji zależności, ładowania klas i metod pakowania. Choć ta zmiana upraszcza wdrażanie w środowiskach takich jak Kubernetes, wymusza również zmianę podejścia w pracy zespołów przyzwyczajonych do rozwiązań opartych na WildFly. Przejście na Quarkus zapewnia znaczące korzyści wydajnościowe i nowocześniejsze środowisko deweloperskie, jednak wymaga starannego planowania i testowania, aby migracja przebiegła pomyślnie.
Kluczowe zmiany wprowadzone w nowych wersjach
Migracja wprowadza istotne zmiany, które wpływają na konfigurację, endpointy oraz implementacje custom providers:
Wymóg HTTPS w trybie produkcyjnym
Uruchamianie Keycloak za pomocą polecenia [keycloak_quarkus_root]/26.1.0/bin/kc.bat start
wymaga teraz certyfikatu HTTPS, ponieważ opcja start
jest przeznaczona do użytku produkcyjnego. Do lokalnego środowiska deweloperskiego należy używać opcji start-dev
.
Usunięcie /auth z podstawowej ścieżki
Segment /auth
został usunięty z domyślnej podstawowej ścieżki. Aplikacje korzystające z endpointów Keycloak muszą zaktualizować swoje konfiguracje, aby uwzględnić tę zmianę.
Zmiany w identyfikatorze realm
W poprzednich wersjach identyfikator realm był identyczny z jego nazwą. Począwszy od Keycloak 21, identyfikator realm jest teraz unikalną, systemowo generowaną wartością. Aplikacje korzystające z identyfikatorów realm muszą uwzględnić tę zmianę podczas migracji.
Wycofanie userLocalStorage
Custom providers korzystający z metody userLocalStorage
interfejsu KeycloakSession
muszą przejść na metodę users
, ponieważ userLocalStorage
została wycofana począwszy od Keycloak 19.
Transport jdbc-ping jako nowy domyślny
W wersji Keycloak 26.1.0 domyślną metodą wykrywania innych węzłów w klastrze stało się korzystanie z bazy danych, zamiast opierania się wyłącznie na multicast. Ta zmiana eliminuje potrzebę dodatkowej konfiguracji sieciowej, szczególnie w środowiskach chmurowych.
Problemy z głównymi migracjami
Podczas migracji Keycloak zdecydowanie zaleca się aktualizowanie wersji krok po kroku, zamiast przeskakiwania przez kilka wydań jednocześnie. Takie stopniowe podejście pozwala na identyfikację i rozwiązywanie problemów na bieżąco, minimalizując ryzyko nieoczekiwanych komplikacji. Przeskakiwanie przez wiele wersji—szczególnie jeśli obejmuje kilkanaście lub więcej wydań—może znacznie skomplikować proces z uwagi na nagromadzone zmiany, wycofane funkcje oraz zmiany w architekturze, takie jak przejście na Quarkus. Realizowanie zmian związanych z kompatybilnością i konfiguracją etapami pozwala na lepszą kontrolę nad migracją oraz redukcję przestojów i zakłóceń w środowiskach produkcyjnych.
Jednak w wielu przypadkach konieczna staje się duża, jednorazowa migracja, na przykład z Keycloak 12 bezpośrednio do Keycloak 26, co stanowi wyzwanie, które zespoły muszą skutecznie rozwiązać. Proces ten często wiąże się z istotnymi zmianami zarówno w samym serwerze Keycloak, jak i w aplikacjach zależnych, szczególnie w klientach frontendowych korzystających z jego API.
W tym przewodniku przedstawimy jak podejść do przeprowadzenia takiej dużej migracji.
Konfiguracja Dockerfile
W naszym przykładowym projekcie wszystkie niestandardowe motywy oraz rozszerzenia SPI (Service Provider Interface) zostały bezpośrednio skopiowane do bazowego obrazu Keycloak, bez dedykowanego procesu budowania. Było to zrealizowane w standardowy sposób stosowany dla WildFly.
FROM quay.io/keycloak/keycloak:12.0.2
COPY themes/custom-theme /opt/jboss/keycloak/themes/custom-theme
COPY api-extensions/target/spi-resource-0.0.1-SNAPSHOT.jar
ENTRYPOINT /opt/jboss/tools/docker-entrypoint.sh -b 0.0.0.0
Nowe podejście może wykorzystywać proces wieloetapowy z oddzielnymi kontenerami, takimi jak:
FROM eclipse-temurin:17-jdk as spi_builder
[…]
FROM quay.io/keycloak/keycloak:$BASE_IMAGE_TAG as keycloak_builder
[…]
FROM quay.io/keycloak/keycloak:$BASE_IMAGE_TAG
SPI jest budowane podczas procesu budowania kontenera przy użyciu narzędzia Maven. Takie podejście zapewnia pobranie zależności oraz optymalizację wygenerowanego pliku JAR do wdrożenia.
### Runtime dependencies build container
FROM registry.access.redhat.com/ubi9 AS runtime_dependencies_builder
RUN mkdir -p /mnt/rootfs
RUN dnf install --installroot /mnt/rootfs curl --releasever 9 --setopt install_weak_deps=false --nodocs -y \
&& dnf --installroot /mnt/rootfs clean all
### SPI build container
FROM eclipse-temurin:17-jdk as spi_builder
ARG BASE_IMAGE_TAG
WORKDIR /workspace/app
COPY api-extensions/mvnw .
COPY api-extensions/.mvn .mvn
COPY api-extensions/pom.xml .
# dos2unix:
RUN sed -i -e 's/\r//g' mvnw
RUN ./mvnw dependency:go-offline
COPY api-extensions/src src
RUN ./mvnw -o package -DskipTests
Nowy proces kopiuje wiele niestandardowych motywów do Keycloak opartego na Quarkus podczas etapu budowania, zapewniając ich uwzględnienie w finalnym zoptymalizowanym środowisku wykonawczym. Takie podejście poprawia wydajność uruchamiania i jest zgodne z filozofią niezmiennych kontenerów.
### Build container
FROM quay.io/keycloak/keycloak:$BASE_IMAGE_TAG as keycloak_builder
COPY --from=spi_builder /workspace/app/target/spi-resource-0.0.1-SNAPSHOT-jar-with-dependencies.jar /opt/keycloak/providers/
#Copy custom themes
COPY themes/custom-theme /opt/keycloak/themes/custom-theme
#Build an optimized server runtime
RUN /opt/keycloak/bin/kc.sh build
### Runtime container
FROM quay.io/keycloak/keycloak:$BASE_IMAGE_TAG
COPY --from=keycloak_builder /opt/keycloak/ /opt/keycloak/
WORKDIR /opt/keycloak
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
Zasadniczo, wykorzystując budowanie wieloetapowe oraz lekkie obrazy, nowy proces jest zgodny z najlepszymi praktykami dotyczącymi wdrożeń konteneryzowanych. Więcej szczegółów na temat tych kroków znajdziesz tutaj: https://www.keycloak.org/server/containers.
Zmiana domyślnej ścieżki kontekstu /auth
Wraz z przejściem na dystrybucję Keycloak opartą na Quarkus, domyślna ścieżka kontekstu została zmodyfikowana – /auth nie jest już domyślnie częścią URL.
Ta zmiana jest zgodna z celem Quarkusa, jakim jest dostarczenie bardziej zoptymalizowanego i minimalistycznego podejścia do aplikacji webowych, redukując niepotrzebne prefiksy ścieżek.
Dla użytkowników lub aplikacji, które nadal wymagają ścieżki kontekstu /auth, można ją ponownie wprowadzić za pomocą opcji build http-relative-path.
Na przykład, uruchamiając Keycloak przy użyciu następującego polecenia, można przywrócić ścieżkę /auth:
bin/kc.[sh|bat] start-dev --http-relative-path /auth
Lub za pomocą Docker Compose:
KC_HTTP_RELATIVE_PATH: /auth
Pozwala to na zachowanie kompatybilności z istniejącymi klientami lub konfiguracjami, które opierają się na prefiksie /auth. Po określeniu względnej ścieżki Keycloak nadal automatycznie przekieruje żądania z katalogu głównego (np. localhost:8080/) na ścieżkę /auth (np. localhost:8080/auth). Dzięki temu aplikacje lub użytkownicy przyzwyczajeni do wcześniejszej struktury URL mogą nadal działać zgodnie z oczekiwaniami, bez konieczności wprowadzania większych zmian.
Zmiany w zarządzaniu dostawcami
Wraz z przejściem na dystrybucję Keycloak opartą na Quarkus, nastąpiły istotne zmiany w sposobie wdrażania i zarządzania custom providers (SPI). W dystrybucji opartej na WildFly byli oni wdrażani poprzez kopiowanie do katalogu standalone/deployments, a zależności umieszczano w określonych lokalizacjach w strukturze serwera WildFly. Jednak w nowej dystrybucji Quarkus model wdrażania został uproszczony — dostosowani dostawcy powinni być teraz kopiowani do katalogu /providers.
Dodatkowo Quarkus nie obsługuje formatu pakowania EAR ani plików jboss-deployment-structure.xml, które były powszechnie wykorzystywane w dystrybucji WildFly do konfiguracji wdrożeń i zarządzania zależnościami. W efekcie proces pakowania został uproszczony, ale dostosowane konfiguracje, które wcześniej były realizowane za pomocą tych plików, muszą być teraz obsługiwane w inny sposób.
Co więcej, jeśli dostosowani dostawcy korzystali z API JavaEE, takich jak sesyjne lub bezstanowe komponenty (session/stateless beans), nie będą one już obsługiwane w dystrybucji Quarkus.
Migracja niestandardowych motywów
Poprzedni Keycloak korzystał z silnika szablonów FreeMarker do renderowania dynamicznych treści w motywach.
Choć podejście to jest nadal stosowane w nowych wersjach (szczególnie w motywach v1 i v2), wprowadzono aktualizacje w składni szablonów oraz strukturze motywów, aby dostosować je do nowej architektury Quarkus. Niestandardowe szablony mogą wymagać dostosowania, aby były kompatybilne z nowszymi wersjami FreeMarker, ponieważ struktura motywów uległa pewnym zmianom.
Dodatkowo niektóre funkcje i makra szablonów, dostępne w starszych wersjach, takich jak Keycloak 12, mogły zostać wycofane lub zastąpione bardziej wydajnymi odpowiednikami.
Motywy, które zostały wcześniej dostosowane, prawdopodobnie nie obsługują trybu ciemnego. Aby uniknąć problemów bez konieczności całkowitego ich przepisywania, najprostszym rozwiązaniem jest dodanie opcji darkMode=false w pliku theme.properties. Co więcej, od wersji 26.1.0 w zakładce „Themes” pojawiły się przełączniki umożliwiające włączanie trybu ciemnego dla poszczególnych realmów.
Dostosowanie nowego serwera Keycloak do współpracy z frontendem klienta w starszej wersji
Problemy związane z checkLoginIframe
W jednym z naszych projektów musieliśmy zaktualizować Keycloak o 14 wersji. Jednak z różnych powodów nie mogliśmy zaktualizować frontendu, który działał na dość starej wersji Angulara oraz bibliotece keycloak-angular. Dlatego teraz omówimy modyfikacje, które musieliśmy wprowadzić, aby przywrócić funkcjonalność procesu logowania.
Keycloak-angular to biblioteka typu wrapper dla keycloak-js, która ułatwia jego wykorzystanie w aplikacjach Angular. Rozszerza oryginalne funkcjonalności o dodatkowe możliwości i wprowadza nowe metody, które ułatwiają integrację w aplikacjach Angular. Biblioteka oferuje również podstawową implementację AuthGuard, umożliwiając dostosowanie logiki autoryzacji. Dodatkowo można korzystać z HttpClient Interceptor, który dodaje nagłówek autoryzacyjny do wybranych żądań HTTP.
"keycloak-angular": "^8.1.0",
"keycloak-js": "^12.0.4",
Po zintegrowaniu nowej wersji Keycloak (26.1.0) ze starym frontendem klienta napotkaliśmy problem, który pojawiał się po zalogowaniu i objawiał się w następujący sposób:
Ta opcja określa, czy Keycloak powinien sprawdzać status logowania za pomocą iframe. Należy jej używać ostrożnie, ponieważ niewłaściwa konfiguracja może prowadzić do problemów, takich jak ciągłe przeładowywanie strony. Nowsze wersje Keycloak mogły ulepszyć lub zmienić sposób zarządzania sesjami, szczególnie w kontekście plików cookie typu cross-site, przepływów uwierzytelniania lub obsługi iframe (setupCheckLoginIframe, check3pCookiesSupported). Te zmiany mogą wpływać na sposób, w jaki frontend obsługuje stany logowania, zwłaszcza jeśli korzysta z przestarzałych metod sprawdzania statusów logowania lub przetwarzania callbacków.
Biorąc pod uwagę znaczną różnicę wersji między frontendem a serwerem, jednym z przydatnych rozwiązań może być wyłączenie opcji setupCheckLoginIframe, co może również pomóc w sytuacjach, gdy po aktualizacji występują nieskończone pętle przekierowań.
Oto przykład, jak wyłączyć tę opcję podczas inicjalizacji:
function initializeKeycloak(keycloak: KeycloakService, permissionsService: PermissionsService)
{
return () =>
keycloak.init({
config: {
url: environment.keycloakUrl,
realm: 'test-realm',
clientId: 'test-realm-web',
},
initOptions: {
checkLoginIframe: false
}
}).then(() => permissionsService.init());
}
Brak klucza nonce w żądaniu
W nowszych wersjach Keycloak, zgodnie ze specyfikacją OpenID Connect Core 1.0, klucz nonce jest teraz dodawany do tokena ID tylko wtedy, gdy parametr ten został uwzględniony w żądaniu autoryzacyjnym. Zgodnie ze specyfikacją, klucz nonce jest obowiązkowy w tokenie ID, ale nie powinien być zawarty w tokenach po żądaniu odświeżenia. Wcześniej klucz nonce był dodawany do wszystkich tokenów (Access, Refresh i ID) we wszystkich odpowiedziach, w tym także w odpowiedziach odświeżających.
W rezultacie korzystanie ze starszej wersji adaptera keycloak-js może powodować problemy z logowaniem, takie jak błędy „Invalid nonce, clearing token” lub nieskończone pętle przekierowań po próbach logowania. Aby rozwiązać ten problem, użytkownicy mogą dodać predefiniowany mapper „Nonce backwards compatible” za pomocą przycisku „By Configuration” w dedykowanym zakresie klienta. Więcej informacji można znaleźć w oficjalnej dokumentacji Keycloak (https://www.keycloak.org/docs/latest/upgrading/index.html#nonce-claim-is-only-added-to-the-id-token).
Problemy z przekierowaniem URI po wylogowaniu
Zgodnie z informacjami zawartymi w notatkach do wydania wersji 18, Keycloak nie obsługuje już parametru redirect_uri podczas wylogowywania. Zamiast tego należy używać parametru post_logout_redirect_uri wraz z parametrem client_id lub id_token_hint. W praktyce oznacza to, że podczas wywoływania funkcji wylogowania należy zastąpić redirect_uri parametrem post_logout_redirect_uri.
W naszym przypadku (przy użyciu starszej wersji keycloak-js) proces wylogowania można zaimplementować w następujący sposób:
window.location.replace(this.keycloak['_instance']['endpoints'].logout() +
'?post_logout_redirect_uri=' + encodeURIComponent(window.location.origin) +
'&client_id=test-realm-web');
Ta zmiana powinna rozwiązać najczęstsze problemy z przekierowaniami po wylogowaniu z aplikacji.
Podsumowanie
W ciągu ostatnich kilku lat Keycloak przeszedł znaczące zmiany, szczególnie te wprowadzone podczas migracji z WildFly na Quarkus. Zmiany te były konieczne dla poprawy wydajności, bardziej efektywnego wykorzystania zasobów oraz lepszej skalowalności.
Choć proces migracji może wydawać się trudny, jest on zazwyczaj wykonalny, nawet w przypadku starszych wersji. Stopień trudności migracji w dużej mierze zależy jednak od konkretnego przypadku, zwłaszcza od poziomu dostosowania. Na przykład, jeśli motywy były mocno zmodyfikowane w poprzedniej wersji Keycloak, ich dostosowanie do nowszych dystrybucji może wymagać więcej czasu i wysiłku, ponieważ struktura i silniki szablonów uległy zmianie.
Podobnie integracje z systemami starszej generacji mogą wymagać starannego planowania, aby zapewnić ich kompatybilność z nowszymi wersjami Keycloak. Z drugiej strony, w przypadku standardowych konfiguracji z minimalnym stopniem dostosowania, przejście na nową wersję jest zazwyczaj płynniejsze i szybsze. Proces migracji może być również wspierany przez szczegółową dokumentację oraz społeczność, która znacznie się rozwinęła w ostatnich latach.
Podsumowując, choć każdy projekt migracyjny niesie ze sobą własne wyzwania, to przy odpowiednim planowaniu i testowaniu przejście na nowszą wersję Keycloak zazwyczaj nie jest zbyt skomplikowane. Długoterminowe korzyści z aktualizacji, takie jak poprawiona wydajność i funkcje bezpieczeństwa, sprawiają, że wysiłek ten jest wart podjęcia.