Jedną z największych zalet, jakie Keycloak oferuje jest Single Sign-On (SSO). Funkcja ta znacząco usprawnia zarządzanie użytkownikami, upraszcza procesy uwierzytelniania w aplikacjach firmowych i stanowi skuteczne rozwiązanie w zakresie wyzwań związanych z bezpieczeństwem. Dziś przyjrzymy się, jak działa oraz jak skonfigurować przykładową integrację.
SSO (Single Sign-On)
SSO to protokół umożliwiający użytkownikom uwierzytelnianie i uzyskiwanie dostępu do wielu aplikacji za pomocą jednego zestawu danych logowania. Takie podejście jest niezwykle wygodne, ponieważ eliminuje potrzebę zapamiętywania wielu haseł lub wielokrotnego logowania się. Co więcej, SSO zwiększa bezpieczeństwo, zmniejszając ryzyko związane ze słabymi, powtórnie używanymi lub zgubionymi hasłami.
Centrum SSO stanowi dostawca tożsamości (IdP), który działa jak centralny serwer uwierzytelniający. Gdy użytkownicy logują się do swojej pierwszej aplikacji, są przekierowywani do IdP, gdzie podają swoje dane uwierzytelniające. Po pomyślnym uwierzytelnieniu IdP inicjuje sesję SSO i generuje zaszyfrowany token dostępu, który aplikacja wykorzystuje do potwierdzenia tożsamości użytkownika.
Po aktywacji sesji SSO użytkownik może uzyskać dostęp do innych zaufanych aplikacji bez konieczności ponownego logowania. Kiedy druga aplikacja wymaga uwierzytelnienia, komunikuje się z IdP, który weryfikuje aktywną sesję użytkownika i wydaje kolejny token dostępu, umożliwiając płynny dostęp bez ponownego wprowadzania danych logowania.
Nowoczesne rozwiązania IAM ułatwiają implementację SSO w różnych aplikacjach, często wykorzystując otwarte standardy, takie jak OAuth 2.0 i OpenID Connect (OIDC). Standardy te umożliwiają uwierzytelnianie nie tylko w aplikacjach wewnętrznych, ale także w tych, które opierają się na zewnętrznych dostawcach tożsamości. Dodatkowo SSO obsługuje logowanie za pomocą mediów społecznościowych, co pozwala użytkownikom na uwierzytelnienie przy użyciu istniejących danych logowania z platform takich jak Google, Facebook czy Twitter.
Typy SSO
Podczas wdrażania i zarządzania Single Sign-On (SSO) kluczowe jest zrozumienie różnych protokołów i standardów, które umożliwiają jego działanie. Do najczęściej stosowanych należą Security Assertion Markup Language (SAML) oraz OpenID Connect (OIDC). Keycloak obsługuje oba te protokoły, co czyni je głównym punktem naszej dyskusji. Warto jednak zauważyć, że inne protokoły, takie jak Kerberos, również odgrywają rolę w niektórych scenariuszach SSO.
Security Access Markup Language (SAML)
SAML to standard oparty na XML, zaprojektowany do kodowania i wymiany informacji o tożsamości pomiędzy aplikacjami. Stał się on fundamentem dla SSO, umożliwiając bezpieczne potwierdzanie żądań uwierzytelniania w aplikacjach internetowych. SAML 2.0, najczęściej stosowana wersja, jest zoptymalizowana specjalnie pod kątem środowisk przeglądarkowych, pozwalając na bezpieczne przekazywanie informacji o użytkownikach za pośrednictwem przeglądarek internetowych. Ze względu na swoją rozwlekłość i mniejszą efektywność przetwarzania danych w porównaniu do nowoczesnych standardów, SAML najlepiej sprawdza się w starszych oraz korporacyjnych aplikacjach internetowych, zwłaszcza tych działających wewnątrz organizacji.
OpenID Connect (OIDC)
OIDC to rozszerzenie protokołu OAuth 2.0, które dodaje informacje o użytkownikach i umożliwia SSO. Wykorzystuje JSON oraz RESTful API do wymiany danych, co sprawia, że jest szybkie i łatwe do integracji, zwłaszcza w środowiskach mobilnych i opartych na chmurze. OIDC jest szczególnie przydatne w scenariuszach związanych z logowaniem przez media społecznościowe (np. Google, Facebook) oraz zewnętrznymi interfejsami API. Jest to najlepszy wybór w sytuacjach, gdy aplikacje wymagają elastycznego, skalowalnego uwierzytelniania opartego na tokenach i zapewniającego wysoki poziom bezpieczeństwa.
Zalety i wady wdrożenia SSO
Kluczowe korzyści Single Sign-On (SSO) to:
- SSO ogranicza potrzebę zapamiętywania wielu nazw użytkowników i haseł, konsolidując uwierzytelnianie do jednego zestawu danych logowania.
- Redukuje liczbę resetów haseł i problemów z logowaniem, co zmniejsza obciążenie działu IT i prowadzi do oszczędności kosztów.
- Eliminuje przerwy spowodowane wielokrotnym logowaniem i zarządzaniem hasłami, pozwalając użytkownikom szybko uzyskać dostęp do potrzebnych zasobów i skupić się na zadaniach. Usprawnia proces logowania oraz umożliwia wylogowanie jednym kliknięciem z wielu aplikacji.
- Centralizacja danych użytkowników ułatwia administratorom zarządzanie i dostosowywanie uprawnień dostępu w całej sieci, zapewniając lepszą kontrolę.
- Konsolidacja danych logowania zmniejsza ryzyko związane ze słabym zarządzaniem hasłami. Administratorzy mogą łatwiej wyłączać konta w razie potrzeby, co podnosi ogólny poziom bezpieczeństwa.
Podsumowując, SSO poprawia doświadczenie użytkowników, zwiększa produktywność, wzmacnia bezpieczeństwo i upraszcza zadania administracyjne, centralizując proces uwierzytelniania i ułatwiając zarządzanie dostępem.
Potencjalne wady SSO
Pojedynczy punkt awarii (SPOF)
Jeśli dostawca SSO doświadczy awarii lub zostanie naruszony, użytkownicy mogą utracić dostęp do wielu aplikacji jednocześnie.Złożoność wdrożenia
Konfiguracja i utrzymanie systemu SSO może być technicznie wymagające, szczególnie w środowiskach zróżnicowanych pod względem aplikacji i protokołów. Nie wszystkie aplikacje natywnie obsługują SSO, co może wymagać niestandardowych integracji.Problemy ze skalowalnością
W środowiskach o dużym ruchu system SSO musi obsługiwać znaczne obciążenia, co może wymagać dodatkowych zasobów oraz starannego planowania przyszłych integracji.
SSO z Keycloak i Spring
Teraz omówimy, jak skonfigurować prosty mechanizm SSO przy użyciu Spring Security, biblioteki keycloak-angular oraz Keycloak jako dostawcy tożsamości. Wybór Keycloak jest podyktowany kilkoma czynnikami. Wykorzystuje on dobrze ugruntowany standard OpenID Connect, zapewniając szeroką kompatybilność. Wyróżnia się również dużą liczbą gotowych przykładów integracji zarówno dla aplikacji front-end, jak i back-end. Oferuje także znaczną elastyczność dzięki rozszerzeniom opartym na Javie, umożliwiając łatwą personalizację.
Aby uruchomić demo SSO, przejdziemy przez przygotowanie serwera autoryzacji, serwera zasobów oraz dwóch różnych aplikacji klienckich. Gdy użytkownik spróbuje uzyskać dostęp do zasobu jednej z aplikacji klienckich, powinien zostać przekierowany do serwera autoryzacji w celu uzyskania tokena. Keycloak zarządza procesem logowania, a po zalogowaniu użytkownika do pierwszej aplikacji klienckiej, jeśli uzyska on dostęp do drugiej aplikacji klienckiej z tej samej przeglądarki, nie będzie musiał logować się ponownie, ponieważ sesja SSO pozostaje aktywna. W tym przykładzie użyjemy klienta OIDC obsługującego OAuth2 oraz Authorization Code Flow do zarządzania procesem uwierzytelniania między punktami końcowymi.
Serwer autoryzacji
Do realizacji zadań dostawcy tożsamości (Identity Provider) lub serwera autoryzacji możemy wykorzystać obraz Dockera z najnowszą wersją Keycloak. Dzięki wdrożeniu za pomocą pliku docker-compose możemy szybko przygotować i skonfigurować środowisko, w tym bazę danych, bez potrzeby ręcznej instalacji. Prosta konfiguracja docker-compose będzie zawierać dwie usługi: Keycloak oraz bazę danych PostgreSQL.
x-keycloak: &keycloak
build: keycloak
ports:
– „8080:8080”
depends_on:
– db-postgres-keycloak
x-common-variables: &common-variables
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
KC_HOSTNAME_STRICT: „false”
KC_HTTP_RELATIVE_PATH: /auth
KC_HTTP_ENABLED: 'true’
KC_LOG_LEVEL: „INFO,io.quarkus.http.access-log:DEBUG”
KC_DB: postgres
KC_DB_URL_HOST: db-postgres-keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: password
KC_DB_SCHEMA: public
QUARKUS_HTTP_ACCESS_LOG_ENABLED: 'true’
services:
keycloak:
<<: *keycloak
environment:
<<: *common-variables
profiles: [„example”]
command: start –optimized
db-postgres-keycloak:
profiles: [„example”]
image: postgres:15
environment:
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
POSTGRES_DB: keycloak
Po uruchomieniu kontenerów możemy zalogować się do konsoli administracyjnej (dostępnej pod adresem http://localhost:8080). Zanim jednak przejdziemy do konfiguracji klientów w ramach realm, warto poświęcić chwilę na zapoznanie się z ustawieniami w sekcji Realm Settings -> Sessions.
SSO konfiguracja sesji
Podczas konfigurowania nowego realm możemy dostosować ustawienia zarządzania sesjami, aby zrównoważyć bezpieczeństwo i wygodę użytkowników. Ustawienia te określają, jak długo użytkownicy pozostają uwierzytelnieni oraz warunki, w których muszą ponownie się zalogować. Poniżej opisujemy najważniejsze z nich:
SSO Session Idle – to ustawienie kontroluje, jak długo użytkownik może pozostawać nieaktywny, zanim jego sesja wygaśnie. Jeśli użytkownik nie podejmie żadnej aktywności przez określony czas, będzie musiał ponownie się uwierzytelnić przy następnej interakcji z aplikacją. Licznik jest resetowany, gdy klient wysyła żądania odświeżenia tokena.
SSO Session Max – parametr ten definiuje maksymalny czas trwania sesji, niezależnie od aktywności użytkownika. Gdy sesja przekroczy ten czas, użytkownik zostanie wylogowany i poproszony o ponowne zalogowanie się.
SSO Session Idle Remember Me oraz SSO Session Max Remember Me – działają podobnie jak parametry SSO Session, ale odnoszą się do sytuacji, gdy użytkownik zaznaczył opcję Remember Me (Zapamiętaj mnie).
Client Session Idle oraz Client Session Max – te parametry powinny mieć krótsze wartości czasu niż ogólne ustawienia SSO. Określają one maksymalny okres ważności tokena odświeżania i mogą być nadpisane dla poszczególnych klientów w ich ustawieniach.
Dostosowanie tych ustawień pozwala precyzyjnie zarządzać sesjami użytkowników, zwiększając kontrolę nad bezpieczeństwem aplikacji oraz optymalizując doświadczenie użytkowników.
Serwer zasobów
Jednym z klientów realm będzie serwer zasobów, który pełni podwójną rolę – jako klient Keycloak oraz backend dla dwóch różnych aplikacji uczestniczących w opisanym przepływie. Proces integracji aplikacji Spring Boot z Keycloak jest bardzo podobny do tego, który opisaliśmy w jednym z wcześniejszych wpisów (https://inero-software.com/pl/zabezpieczanie-punktow-koncowych-java-spring-za-pomoca-keycloak/).
Dlatego nie będziemy tutaj skupiać się na samej aplikacji Java. Skonfigurowany w ten sposób serwer zasobów będzie wystawiał przykładowy endpoint dostępny tylko dla użytkowników uwierzytelnionych w ramach tego realm.
Serwer zasobów musi zarządzać zasobami w ramach realm, dlatego w Keycloak należy zaznaczyć opcję Authorization. To ustawienie jest przeznaczone głównie dla serwerów zasobów, które potrzebują dostępu do różnych endpointów, takich jak Token Endpoint.
W tej konfiguracji klient jest ustawiony jako confidential (poufny) z sekretem, który musi być współdzielony zarówno przez serwer Keycloak, jak i samą aplikację. Sekret można wygenerować w Admin Console, a następnie umieścić go w pliku application.properties aplikacji Spring, aby zapewnić bezpieczną komunikację.
Pozostałe pola formularza można pozostawić z domyślnymi wartościami.
Frontend clients
Konfiguracja klientów frontendu jest dość podobna do poprzedniej, jednak warto zwrócić uwagę na pewne różnice. W przypadku klientów działających w przeglądarce nie ustawiamy ich jako confidential. Opcja „Authorization” również nie jest tutaj wymagana. Kluczowym aspektem jest właściwa konfiguracja Redirect URIs oraz Web Origins. Zazwyczaj mogą one być takie same, co zapewnia, że Keycloak prawidłowo rozpozna dozwolone źródła, z których aplikacja frontendowa może wykonywać żądania.
Jednak nie zaleca się polegania na wildcardach (*) w Redirect URIs. Najnowsza specyfikacja OAuth 2.1 wymaga, aby URI były porównywane przy użyciu dokładnego dopasowania ciągu znaków.
Aby uwierzytelnić użytkownika i wyświetlić stronę logowania Keycloak w naszym projekcie Angular, użyjemy Injection Token.
function initializeKeycloak(keycloak: KeycloakService) {
return () =>
keycloak.init({
config: {
url: environment.keycloakUrl,
realm: 'sso-realm',
clientId: 'sso-app-1',
},
initOptions: {
checkLoginIframe: false,
scope: 'sso-resource-server'
}
});
}
Powyższa funkcja przyjmuje jako argument KeycloakService, czyli obiekt z biblioteki keycloak-angular, dzięki czemu możemy go skonfigurować, podając URL serwera, nazwę realm oraz identyfikator klienta aplikacji, który został utworzony w poprzednim kroku. Następnie musimy zarejestrować tę funkcję w pliku app.module.ts jako provider:
providers: [
{
provide: APP_INITIALIZER,
useFactory: initializeKeycloak,
multi: true,
deps: [KeycloakService],
},
],
Kolejnym krokiem będzie utworzenie Guard, który zabezpieczy ścieżki w aplikacji. Biblioteka, której używamy, dostarcza już wstępnie skonfigurowaną, abstrakcyjną klasę KeycloakAuthGuard, którą rozszerzymy, tworząc własny Guard. Następnie musimy nadpisać metodę isAccessAllowed.
public async isAccessAllowed(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
// Force the user to log in if currently unauthenticated.
if (!this.authenticated) {
await this.keycloak.login({
redirectUri: window.location.origin + '/#/' + state.url
});
}
// Get the roles required from the route.
const requiredRoles = route.data['roles'];
// Allow the user to proceed if no additional roles are required to access the route.
if (!(requiredRoles instanceof Array) || requiredRoles.length === 0) {
return true;
}
// Allow the user to proceed if all the required roles are present.
return requiredRoles.every((role) => this.roles.includes(role));
}
Następnie musimy przypisać AuthGuard do określonych ścieżek w module routingu. Po poprawnej konfiguracji wszystkich komponentów biblioteki keycloak-angular, użytkownik powinien zostać przekierowany na stronę logowania Keycloak, a po pomyślnej autoryzacji uzyska dostęp do chronionych zasobów.
Test i podsumowanie
Aby przetestować funkcjonalność SSO, uruchom serwer zasobów (aplikację Spring) oraz oba klientów działających w przeglądarce. Gdy wszystkie komponenty będą działały, otwórz przeglądarkę i zaloguj się do jednej z aplikacji frontendowych. Następnie otwórz nową kartę lub okno i przejdź do drugiej aplikacji Angular. Po kliknięciu przycisku logowania powinieneś zostać bezpośrednio przekierowany do aplikacji i uzyskać dostęp do chronionego endpointu.
W ten sposób można zobaczyć, jak wbudowane funkcje Keycloak upraszczają zarządzanie uprawnieniami dostępu. Wykorzystując Keycloak jako dostawcę tożsamości (Identity Provider), możemy skonfigurować system, w którym użytkownicy muszą zalogować się tylko raz, aby uzyskać dostęp do różnych połączonych aplikacji. Centralizując dane logowania użytkowników, zwiększamy zarówno bezpieczeństwo, jak i doświadczenie użytkownika, a także ograniczamy ryzyko związane z podatnościami wynikającymi z haseł.