Aplikacja full-stack (SPA + REST API) służąca do zarządzania katalogiem książek. Głównym celem projektu nie była tylko funkcjonalność, ale przede wszystkim implementacja zaawansowanego, bezpiecznego systemu uwierzytelniania i autoryzacji w architekturze bezstanowej.
Projekt rozwiązuje typowe problemy bezpieczeństwa aplikacji webowych (XSS, CSRF) oraz ograniczenia JWT (brak możliwości natychmiastowego wylogowania) poprzez zastosowanie Redis Blacklist.
To, co wyróżnia ten projekt pod kątem technicznym:
- Bezstanowa architektura: Serwer nie przechowuje sesji w pamięci RAM aplikacji.
- Bezpieczeństwo XSS: Tokeny dostępowe (Access Tokens) są przesyłane wyłącznie w ciasteczkach
HttpOnlyiSameSite=Strict(niedostępnych dla JavaScript). - Bezpieczeństwo CSRF: Implementacja wzorca Double Submit Cookie przy użyciu niestandardowego interceptora Axios i tokenów XSRF.
- Implementacja pary tokenów: krótkożyjący Access Token (np. 15 min) i długożyjący Refresh Token (np. 7 dni).
- Silent Refresh: Frontend automatycznie (poprzez
Axios Interceptors) wykrywa wygaśnięcie sesji, odświeża token w tle i ponawia przerwane żądanie, zapewniając płynne działanie dla użytkownika.
- Rozwiązanie problemu "stateless JWT logout".
- Przy wylogowaniu identyfikator tokena (
jti) trafia na czarną listę w bazie Redis. - Filtr bezpieczeństwa (
JwtAuthenticationFilter) sprawdza Redis przy każdym żądaniu, blokując dostęp natychmiast po wylogowaniu, nawet jeśli token JWT jest kryptograficznie nadal ważny.
- Role systemowe: USER oraz MODERATOR.
- Zabezpieczenie endpointów na poziomie metod (
@PreAuthorize).
Proces logowania nie zwraca wrażliwych danych wprost do JavaScriptu. Zamiast tego serwer ustawia bezpieczne ciasteczko, które jest automatycznie i niewidocznie dla skryptów dołączane do kolejnych zapytań.
Gdy krótkożyjący Access Token wygaśnie, aplikacja nie wylogowuje użytkownika. Frontend automatycznie wykrywa błąd 403 Forbidden, wysyła Refresh Token do endpointu /auth/refresh i ponawia oryginalne zapytanie z nowym tokenem.
W standardowym JWT wylogowanie to tylko usunięcie tokena z przeglądarki. Jeśli token został wcześniej skradziony, nadal działałby do czasu wygaśnięcia.
W tym systemie, przy wylogowaniu identyfikator tokena jti trafia na czarną listę w Redis. Filtr bezpieczeństwa JwtAuthenticationFilter sprawdza Redis przy każdym żądaniu, blokując dostęp natychmiastowo.
Backend:
- Java 17, Spring Boot 3
- Spring Security (CORS, CSRF, konfiguracja łańcucha filtrów)
- Spring Data JPA (Hibernate)
- Spring Data Redis
- MySQL 8.0
Frontend:
- React (Hooks, Context API)
- TypeScript
- Axios (konfiguracja interceptorów)
- MDB Bootstrap
DevOps:
- Docker & Docker Compose (pełna konteneryzacja)
Projekt jest w pełni skonteneryzowany. Aby go uruchomić, potrzeba zainstalowanego Dockera.
-
Sklonuj repozytorium:
git clone https://github.com/Keriw01/BookVibe_Secure_Auth.git
-
Skonfiguruj środowisko: Utwórz plik
.envw głównym katalogu i uzupełnij:APP_MODERATOR_EMAIL=<example@example.com> APP_MODERATOR_PASSWORD=<Example123!> APP_MODERATOR_FULLNAME=<Example> DB_HOST=mysql DB_USER=<Example> DB_PASSWORD=<Example123!> DB_NAME=<example_db> DB_PORT=<PORT_NUMBER> REDIS_HOST=redis REDIS_PORT=<PORT_NUMBER> BACKEND_PORT=<PORT_NUMBER> FRONTEND_PORT=<PORT_NUMBER> JWT_SECRET=<JWT_64_CHARACTERS_256_BITS> JWT_EXPIRATION=<JWT_EXPIRATION_TIME> JWT_REFRESH_EXPIRATION=<JWT_REFRESH_EXPIRATION> DB_INIT_TIMEOUT=<DB_INIT_TIMEOUT> DB_CONN_TIMEOUT=<DB_CONN_TIMEOUT>
-
Uruchom aplikację: Znajdując się w głównym katalogu (tam gdzie
docker-compose.yml):docker-compose up -d --build
-
Dostęp do bazy danych i Redis : Do bazy danych można zalogować się wchodząc w Docker
mysqlopen in terminal:mysql -h 127.0.0.1 -P <PORT_NUMBER> -u root -p
use bookvibe_db; show tables; SELECT * FROM users;
W kontenerze Redis można też wchodząc przez terminal wyświetlić jti kluczy na czarnej liście:
redis-cli keys "blacklist:*"
- Frontend Documentation - opis funkcjonalności, komponentów i diagram przypadków użycia.
- Backend Documentation - dokumentacja API, opis endpointów i struktury bazy danych.


