# Keycloak OAuth Authentication

- **Complexity:** High
- **Stack:** Full-stack (Backend-heavy)

**As a** platform operator, **I want to** replace the local password management with Keycloak-based OAuth **so that** authentication is handled by a dedicated identity provider with industry-standard security.

## Description

The application currently manages user credentials locally: passwords are hashed with BCrypt and stored in the PostgreSQL database, and JWTs are issued by a custom `AuthService` using the `jjwt` library. The `SecurityConfig` defines a stateless filter chain with a `JwtAuthFilter` that validates these self-issued tokens. Registration and login are handled by `AuthController` endpoints (`/auth/register`, `/auth/login`).

This story replaces the local authentication mechanism with Keycloak as an external OpenID Connect (OIDC) identity provider. The backend becomes a resource server that validates tokens issued by Keycloak instead of issuing its own. The frontend redirects users to Keycloak for login and handles the OAuth authorization flow to obtain access tokens. User roles are mapped from Keycloak realm or client roles to the application's existing authorization model.

## Acceptance Criteria

- [ ] Keycloak runs as a service in the Docker Compose setup with a pre-configured realm
- [ ] Clicking "Login" in the frontend redirects to the Keycloak login page
- [ ] After authentication, the user is redirected back to the application with a valid session
- [ ] The frontend stores tokens securely and attaches them to API requests
- [ ] Token refresh works: a user session does not expire while the user is actively using the application
- [ ] The backend validates access tokens issued by Keycloak using Spring Security's OAuth2 resource server support
- [ ] The backend rejects requests with missing or invalid Keycloak-issued tokens
- [ ] Admin and customer roles in Keycloak map to the application's existing role-based access
- [ ] The custom `JwtAuthFilter`, local JWT signing logic, and `/auth/register` + `/auth/login` endpoints are removed
- [ ] The `User` entity is retained for application-specific data but no longer stores passwords
