Помогите настроить взаимодействие 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());
        };
    }
}

keycloak admin console: keycloak admin console


Ответы (0 шт):