Помогите настроить взаимодействие keycloak и приложение spring boot в докере
Много вариантов перепробовал ничего не помогает. При попытке регистрации или логина и при переходе по защищенным url, ошибка страница недоступна, при переходе по публичным url все работает корректно. вот логи:
2025-11-18T08:38:22.129Z DEBUG 1 --- [nio-8091-exec-6] o.s.security.web.FilterChainProxy : Securing GET /favicon.ico
2025-11-18T08:38:22.130Z DEBUG 1 --- [nio-8091-exec-6] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
2025-11-18T08:38:22.130Z DEBUG 1 --- [nio-8091-exec-6] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8091/oauth2/authorization/keycloak
2025-11-18T08:38:22.134Z DEBUG 1 --- [nio-8091-exec-7] o.s.security.web.FilterChainProxy : Securing GET /oauth2/authorization/keycloak
2025-11-18T08:38:22.135Z DEBUG 1 --- [nio-8091-exec-7] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8090/realms/movies_catalog/protocol/openid-connect/auth?response_type=code&client_id=movies_catalog&scope=openid%20profile%20email&state=VfJQczHbuFz6hlV826Ze7sa2f4pb2HD2gekEHIxw-BU%3D&redirect_uri=http://localhost:8091/login/oauth2/code/keycloak&nonce=Ct56-jyXrzQzkpuuGkishx0FSB-N1nSoELDDIfemz5o
2025-11-18T08:38:23.140Z DEBUG 1 --- [nio-8091-exec-8] o.s.security.web.FilterChainProxy : Securing GET /oauth2/authorization/keycloak?
2025-11-18T08:38:23.141Z DEBUG 1 --- [nio-8091-exec-8] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8090/realms/movies_catalog/protocol/openid-connect/auth?response_type=code&client_id=movies_catalog&scope=openid%20profile%20email&state=_rs3HxdkCs_NYRO0SAoOYB1FMXz5yPZVipMlSp_d090%3D&redirect_uri=http://localhost:8091/login/oauth2/code/keycloak&nonce=jRc7ve2F09lZhgQiM_bDTEqyHiBX0yA2MLW8xkIPck8
2025-11-18T08:38:45.426Z DEBUG 1 --- [nio-8091-exec-9] o.s.security.web.FilterChainProxy : Securing GET /login/oauth2/code/keycloak?state=_rs3HxdkCs_NYRO0SAoOYB1FMXz5yPZVipMlSp_d090%3D&session_state=d8bc543c-2ba0-b7ce-635f-2542bcb14935&iss=http%3A%2F%2Flocalhost%3A8090%2Frealms%2Fmovies_catalog&code=0593a006-c960-1b17-a03c-7d7c0f7fd120.d8bc543c-2ba0-b7ce-635f-2542bcb14935.085657e6-edd5-4cfa-99ec-1b1ac1f6b2ba
2025-11-18T08:38:45.472Z DEBUG 1 --- [nio-8091-exec-9] o.s.s.authentication.ProviderManager : Authentication failed with provider OidcAuthorizationCodeAuthenticationProvider since [invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 401 Unauthorized: [no body]
2025-11-18T08:38:45.472Z DEBUG 1 --- [nio-8091-exec-9] .s.a.DefaultAuthenticationEventPublisher : No event was found for the exception org.springframework.security.oauth2.core.OAuth2AuthenticationException
2025-11-18T08:38:45.472Z DEBUG 1 --- [nio-8091-exec-9] o.s.s.web.DefaultRedirectStrategy : Redirecting to /oauth2/authorization/keycloak?error
2025-11-18T08:38:45.481Z DEBUG 1 --- [nio-8091-exec-1] o.s.security.web.FilterChainProxy : Securing GET /oauth2/authorization/keycloak?error
2025-11-18T08:38:45.482Z DEBUG 1 --- [nio-8091-exec-1] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8090/realms/movies_catalog/protocol/openid-connect/auth?response_type=code&client_id=movies_catalog&scope=openid%20profile%20email&state=NcyLWyYe1gXDjA6GDupcJNhFwivqw7K_qjy8BbhvXPQ%3D&redirect_uri=http://localhost:8091/login/oauth2/code/keycloak&nonce=iIb0gcuhK_Zn8dbn5Dx7RMFQd4RQLhvn004Eac9FpRA
2025-11-18T08:38:45.524Z DEBUG 1 --- [io-8091-exec-10] o.s.security.web.FilterChainProxy : Securing GET /login/oauth2/code/keycloak?state=NcyLWyYe1gXDjA6GDupcJNhFwivqw7K_qjy8BbhvXPQ%3D&session_state=d8bc543c-2ba0-b7ce-635f-2542bcb14935&iss=http%3A%2F%2Flocalhost%3A8090%2Frealms%2Fmovies_catalog&code=338fdb26-5efb-2dd0-b1ab-852359f57d5b.d8bc543c-2ba0-b7ce-635f-2542bcb14935.085657e6-edd5-4cfa-99ec-1b1ac1f6b2ba
2025-11-18T08:38:45.557Z DEBUG 1 --- [io-8091-exec-10] o.s.s.authentication.ProviderManager : Authentication failed with provider OidcAuthorizationCodeAuthenticationProvider since [invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 401 Unauthorized: [no body]
2025-11-18T08:38:45.557Z DEBUG 1 --- [io-8091-exec-10] .s.a.DefaultAuthenticationEventPublisher : No event was found for the exception org.springframework.security.oauth2.core.OAuth2AuthenticationException
2025-11-18T08:38:45.557Z DEBUG 1 --- [io-8091-exec-10] o.s.s.web.DefaultRedirectStrategy : Redirecting to /oauth2/authorization/keycloak?error
2025-11-18T08:38:45.564Z DEBUG 1 --- [nio-8091-exec-2] o.s.security.web.FilterChainProxy : Securing GET /oauth2/authorization/keycloak?error
2025-11-18T08:38:45.565Z DEBUG 1 --- [nio-8091-exec-2] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8090/realms/movies_catalog/protocol/openid-connect/auth?response_type=code&client_id=movies_catalog&scope=openid%20profile%20email&state=Ad7N5lcfO3TGIfwyvobJrUu904eeFwIW3AABJF2I2Fg%3D&redirect_uri=http://localhost:8091/login/oauth2/code/keycloak&nonce=8a5PP13AawCSD46TEeXC3UdvurcegmnBMjoRa8wt0ec
вот последний вариант конфигурации:
applciation.yaml
spring:
datasource:
username: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
url: ${POSTGRES_URL}
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: validate
properties:
hibernate:
show_sql: true
format_sql: true
servlet:
multipart:
max-file-size: 5MB
max-request-size: 6MB
security:
oauth2:
client:
provider:
keycloak:
authorization-uri: http://localhost:8090/realms/movies_catalog/protocol/openid-connect/auth
token-uri: http://keycloak:8090/realms/movies_catalog/protocol/openid-connect/token
user-info-uri: http://keycloak:8090/realms/movies_catalog/protocol/openid-connect/userinfo
jwk-set-uri: http://keycloak:8090/realms/movies_catalog/protocol/openid-connect/certs
user-name-attribute: sub
registration:
keycloak:
provider: keycloak
client-id: movies_catalog
client-secret: GTbDbHD7LPt1EYAzKxrcIKdXfEvXq43W
client-name: movies_catalog
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8091/login/oauth2/code/keycloak # Добавьте эту строку
scope: openid, profile, email
# resourceserver:
# jwt:
# issuer-uri: http://localhost:8090/realms/movies_catalog
keycloak:
admin:
url: http://keycloak:8090
realm: movies_catalog
client-id: app-admin
client-secret: RwHGzwL8oud6DHrA7ibLY4YIODDsfIly
server:
port: 8091
app:
image:
bucket: /app/images
logging:
level:
org.springframework.security: DEBUG
org.springframework.security.oauth2: DEBUG
docker-compose.yml
services:
postgres:
container_name: docker_postgres
image: postgres:15
env_file:
- postgres.env
ports:
- "5433:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend_net
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres -d movie_catalog" ]
interval: 5s
timeout: 5s
retries: 5
keycloak:
image: quay.io/keycloak/keycloak:26.4
container_name: keycloak
command:
- start-dev
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_HTTP_PORT: 8090
ports:
- "8090:8090"
networks:
- backend_net
volumes:
- keycloak_data:/opt/keycloak/data
healthcheck:
test: [ "CMD-SHELL", "timeout 1 bash -c 'cat < /dev/null > /dev/tcp/localhost/8090'" ]
interval: 10s
timeout: 5s
retries: 20
start_period: 40s
spring_boot:
container_name: spring_boot
build:
context: .
ports:
- "8091:8091"
env_file:
- postgres.env
depends_on:
keycloak:
condition: service_healthy
postgres:
condition: service_healthy
networks:
- backend_net
volumes:
- ./images:/app/images
networks:
backend_net:
volumes:
postgres_data:
keycloak_data:
SecurityConfiguration.java
@Configuration
@RequiredArgsConstructor
@Slf4j
public class SecurityConfiguration {
private final ClientRegistrationRepository clientRegistrationRepository;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth->
auth.requestMatchers("/movies/**","/genres/**", "/actors/**",
"/users/registration","api/v1/image/**")
.permitAll()
.requestMatchers("users/profile/**")
.hasAnyAuthority("movies_catalog.user", "movies_catalog.admin" )
.anyRequest().authenticated())
.oauth2Login(oauth2 -> {
oauth2.userInfoEndpoint(userInfo-> userInfo.oidcUserService(oAuth2UserService()));
oauth2.defaultSuccessUrl("/movies",true);
oauth2.loginPage("/oauth2/authorization/keycloak");
})
.logout(logout -> logout.logoutSuccessHandler(oidcLogoutSuccessHandler()).invalidateHttpSession(true).clearAuthentication(true)
.deleteCookies("JSESSION"));
return http.build();
}
private LogoutSuccessHandler oidcLogoutSuccessHandler(){
OidcClientInitiatedLogoutSuccessHandler handler =
new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
handler.setPostLogoutRedirectUri("http://localhost:8091/login");
return handler;
}
@Bean
public OAuth2UserService<OidcUserRequest, OidcUser> oAuth2UserService() {
return userRequest -> {
OidcUser oidcUser = new OidcUserService().loadUser(userRequest);
List<String> roles = oidcUser.getClaimAsStringList("roles");
log.warn("User roles: {}", roles );
if (roles == null) {
roles = Collections.emptyList();
}
var mappedAuthorities = roles.stream()
.filter(role -> role.startsWith("movies_catalog."))
.map(SimpleGrantedAuthority::new)
.map(GrantedAuthority.class::cast)
.collect(Collectors.toList());
log.warn("mappedAuthorities: {}", mappedAuthorities );
return new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());
};
}
}
