Spring Boot Rest + Keycloak защита в Докере - не срабатывает перенаправление
Всем привет!
Возникла проблема развертки Spring Boot приложения(микросервисы). По сути роль приложения: обращаться к другому сервису по рест-темплейту и выдавать результат с помощью рест контроллера. К приложению подключен Swagger and Swagger UI, через который происходят авторизация к сервисам через кейлоак(с этим проблем нет), сами сервисы защищены кейклоком через спринг секьюрити (кейклоак поднят в докере).
Логика вызовов методов такова: На каждый метод стоит аннотация с необходимыми ролями пользователя для получения доступа к этому методу. Для того, чтобы обратиться к сервису из вне, необходимо вместе с запросов передать Bearer-token, пример:
В данном примере проиходит авторизация через сваггер юай: сваггер обращается к кейлоку, меня перенаправляет на авторизацию кейлока, ввожу данные пользователя, сваггер получает необходимый токен(это все работает исравно). Дальше при отправки запроса токен приходит мне на сервер, где должен получить ответ от кейлока и либо разрешить войти в метод, либо нет. Как раз на данной стадии по сути не происходит ничего, в ответ на реквест к сервису, получаю пустой респонс, а в хедерах можно увидеть, что закончился таймаут на запрос и кейклоак никак не обрабатывал данные. Если с какого-нибудь метода снять аннотацию с необходимыми ролями, то метод через сваггер работает прекрасно. Если отправлять запрос без токена, в ответ получаю респонс, что неавторизованный доступ. Когда мой сервис блы поднят локально, работало все прекрасно, как только сервис поднял в докере, началась данная проблема. Уже перепробовал множество способов, из подозрений то, что бутовое приложение скорее всего желает обратиться к локалхосту, а обращается к имени сервиса в докер-композе.
Какие есть догадки как исправить данную проблему?
Весь материал ниже предоставляю:
Docker-compose:
keycloak:
image: quay.io/keycloak/keycloak:latest
restart: always
container_name: keycloak
environment:
DB_VENDOR: POSTGRES
DB_ADDR: postgres
DB_DATABASE: keycloak
DB_USER: postgres
DB_SCHEMA: public
DB_PASSWORD: root
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: root
KEYCLOAK_IMPORT: /opt/keycloak/my_realm.json
ports:
- 8080:8080
depends_on:
- postgres
volumes:
- ./keycloak:/opt/keycloak
networks:
- backend
Мой веб сервис в композе:
edge:
build:
context: ./edge-service
dockerfile: Dockerfile-edge
container_name: service-edge
ports:
- 8888:8888
networks:
- backend
depends_on:
- kafka
При запуске приложения, получаю уведомление, что секьюрити работает
При обращение к сервису с bearer токеном, получаю лог:
В ответ получаю:
Пример Рест-Контроллера с методом и маппингом:
@RestController()
@RequestMapping("/json")
public class JsonRestController {
@Autowired
private final RestHandler handler;
@Autowired
private FileRepository fileRepository;
public JsonRestController(RestHandler restHandler) {
this.handler = restHandler;
}
@RolesAllowed({"admin", "user"})
@GetMapping(value = "/id/{id}", produces = "application/json")
@ResponseStatus(HttpStatus.OK)
public Device findById(@PathVariable("id") String id) {
return handler.findById(id);
}
Конфиг Секьюрити:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(
AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider
= keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(
new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.anyRequest()
.permitAll();
http.csrf().disable();
}
}
Конфиг сваггера: (с ним проблем нет, просто для сведения)
@Configuration
public class SpringFoxConfig {
@Value("${keycloak.auth-server-url}")
private String AUTH_SERVER;
@Value("${keycloak.credentials.secret}")
private String CLIENT_SECRET;
@Value("${keycloak.resource}")
private String CLIENT_ID;
@Value("${keycloak.realm}")
private String REALM;
private static final String OAUTH_NAME = "spring_oauth";
private static final String GROUP_NAME = "MICRO-api";
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.onboarding.edgeservice.controllers"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.securitySchemes(Arrays.asList(securityScheme()))
.securityContexts(Arrays.asList(securityContext()));
}
@Bean
public SecurityConfiguration security() {
return SecurityConfigurationBuilder.builder()
.realm(REALM)
.clientId(CLIENT_ID)
.clientSecret(CLIENT_SECRET)
.appName(GROUP_NAME)
.scopeSeparator(" ")
.build();
}
private SecurityScheme securityScheme() {
GrantType grantType =
new AuthorizationCodeGrantBuilder()
.tokenEndpoint(new TokenEndpoint("http://localhost:8080/auth" + "/realms/" + REALM + "/protocol/openid-connect/token", GROUP_NAME))
.tokenRequestEndpoint(
new TokenRequestEndpoint("http://localhost:8080/auth" + "/realms/" + REALM + "/protocol/openid-connect/auth", CLIENT_ID, CLIENT_SECRET))
.build();
return new OAuthBuilder()
.name(OAUTH_NAME)
.grantTypes(Arrays.asList(grantType))
.build();
}
private AuthorizationScope[] scopes() {
AuthorizationScope[] scopes = {
};
return scopes;
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(Arrays.asList(new SecurityReference(OAUTH_NAME, scopes())))
.forPaths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfo(
"My onboarding",
"Some custom description of API.",
"1.0.0",
"Terms of service",
new Contact("Sergey Vasilchenko", "www.example.com", "[email protected]"),
"License of API", "API license URL", Collections.emptyList());
}
}
Кейклоак пропертя в спринговых пропертях:
keycloak.auth-server-url=http://keycloak:8080/auth
keycloak.realm=onboarding
keycloak.resource=dev-client
keycloak.ssl-required=external
keycloak.credentials.secret=<secret code>
keycloak.use-resource-role-mappings=true
keycloak.bearer-only=true
Прошу помощи) если еще необходимо будет какие-то данные - предоставлю)



