From 6f405b41f94fcdd1ef4baacb8eb4868689cc2660 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Fri, 9 Jun 2023 23:02:21 +0200 Subject: [PATCH 01/22] spring updates --- hello-service/build.gradle | 4 ++-- hello-service/gradle/wrapper/gradle-wrapper.properties | 4 ++-- message-service/build.gradle.kts | 8 ++++---- message-service/gradle/wrapper/gradle-wrapper.properties | 4 ++-- ui/pom.xml | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hello-service/build.gradle b/hello-service/build.gradle index 56520cc..cbd7825 100644 --- a/hello-service/build.gradle +++ b/hello-service/build.gradle @@ -1,6 +1,6 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.0.1' + id 'org.springframework.boot' version '3.1.0' id 'io.spring.dependency-management' version '1.1.0' } @@ -18,7 +18,7 @@ repositories { } ext { - set('springCloudVersion', "2022.0.0") + set('springCloudVersion', "2022.0.3") } dependencies { diff --git a/hello-service/gradle/wrapper/gradle-wrapper.properties b/hello-service/gradle/wrapper/gradle-wrapper.properties index 070cb70..aba097b 100644 --- a/hello-service/gradle/wrapper/gradle-wrapper.properties +++ b/hello-service/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/message-service/build.gradle.kts b/message-service/build.gradle.kts index 3a184b8..063033d 100644 --- a/message-service/build.gradle.kts +++ b/message-service/build.gradle.kts @@ -1,10 +1,10 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("org.springframework.boot") version "3.0.1" + id("org.springframework.boot") version "3.1.0" id("io.spring.dependency-management") version "1.1.0" - kotlin("jvm") version "1.7.22" - kotlin("plugin.spring") version "1.7.22" + kotlin("jvm") version "1.8.21" + kotlin("plugin.spring") version "1.8.21" } group = "it.valeriovaudi" @@ -14,7 +14,7 @@ repositories { mavenCentral() } -extra["springCloudVersion"] = "2022.0.0" +extra["springCloudVersion"] = "2022.0.3" dependencies { implementation("org.springframework.cloud:spring-cloud-starter-bootstrap") diff --git a/message-service/gradle/wrapper/gradle-wrapper.properties b/message-service/gradle/wrapper/gradle-wrapper.properties index 070cb70..aba097b 100644 --- a/message-service/gradle/wrapper/gradle-wrapper.properties +++ b/message-service/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/ui/pom.xml b/ui/pom.xml index c77eb74..7611988 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 3.0.1 + 3.1.0 it.valeriovaudi @@ -16,7 +16,7 @@ 17 - 2022.0.0 + 2022.0.3 From 2c4fdd41c3cd5ce68b91472e5cbd36b2069de592 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sat, 10 Jun 2023 01:10:20 +0200 Subject: [PATCH 02/22] WIP: to oauth2 --- .../templates/ui-interface.yml | 18 +++++- helm/spring-cloud-kubernetes-demo/values.yaml | 7 +++ ui/pom.xml | 4 ++ .../it/valeriovaudi/ui/UiApplication.java | 58 +++++++++---------- 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml b/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml index e746919..c4170f8 100644 --- a/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml +++ b/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml @@ -5,7 +5,6 @@ metadata: namespace: {{ .Release.Namespace }} data: application.yaml: |- - testValue: it is a test value server: forward-headers-strategy: framework @@ -14,6 +13,23 @@ data: redis: host: {{ .Release.Namespace }}-redis-master + security: + oauth2: + client: + registration: + client: + client-id: {{ .Values.keycloak.sso.clientId }} + client-secret: {{ .Values.keycloak.sso.clientSecret }} + client-name: keycloak + provider: keycloak + scope: + - openid + authorization-grant-type: authorization_code + provider: + keycloak: + issuer-uri: {{ .Values.keycloak.tenantUrl }} + user-name-attribute: preferred_username + cloud: gateway: routes: diff --git a/helm/spring-cloud-kubernetes-demo/values.yaml b/helm/spring-cloud-kubernetes-demo/values.yaml index fb24731..5ecc82f 100644 --- a/helm/spring-cloud-kubernetes-demo/values.yaml +++ b/helm/spring-cloud-kubernetes-demo/values.yaml @@ -14,7 +14,14 @@ helloService: pullPolicy: Always tag: latest +keycloak: + tenantUrl: http://keycloak.local + sso: + clientId: xxx + clientSecret: xxx + ui: + baseUrl: http://localhost:8080 replicas: 2 image: pullPolicy: Always diff --git a/ui/pom.xml b/ui/pom.xml index 7611988..8e7fed6 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -20,6 +20,10 @@ + + org.springframework.boot + spring-boot-starter-oauth2-client + org.springframework.cloud spring-cloud-starter-bootstrap diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 91d80f9..55e977a 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -4,13 +4,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.web.server.SecurityWebFilterChain; - -import static java.util.Arrays.asList; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; +import org.springframework.security.web.SecurityFilterChain; @SpringBootApplication public class UiApplication { @@ -24,31 +21,30 @@ public static void main(String[] args) { @Configuration(proxyBeanMethods = false) class SecurityConfig { - @Bean - public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - return http.csrf().disable().authorizeExchange() - .pathMatchers("/index.html").hasRole("USER") - .pathMatchers("/messages.html").hasRole("ADMIN") - .anyExchange().permitAll() - .and().formLogin() - .and().logout() - .and().build(); - } @Bean - public MapReactiveUserDetailsService userDetailsService() { - UserDetails user = User.builder() - .username("user") - .password("{noop}secret") - .roles("USER") - .build(); - - UserDetails admin = User.builder() - .username("admin") - .password("{noop}secret") - .roles("ADMIN") - .build(); - - return new MapReactiveUserDetailsService(asList(admin, user)); + public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { + http.csrf(AbstractHttpConfigurer::disable); + http.headers(configurer -> configurer.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)); + + http.logout(logoutConfigurer -> + logoutConfigurer.deleteCookies("opbs") + .invalidateHttpSession(true) + .logoutSuccessUrl("/index") + ); + + + http.oauth2Login(loginConfigurer -> loginConfigurer.defaultSuccessUrl("/index")); + + http.authorizeHttpRequests( + auth -> + auth + .requestMatchers("/index.html").hasRole("USER") + .requestMatchers("/messages.html").hasRole("USER") + .anyRequest().permitAll() + ); + + return http.build(); } + } \ No newline at end of file From 69b8471654f88abb5478ffe24f3bc3be7982e205 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sat, 10 Jun 2023 01:33:51 +0200 Subject: [PATCH 03/22] WIP: to oauth2 --- helm/spring-cloud-kubernetes-demo/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/spring-cloud-kubernetes-demo/Chart.yaml b/helm/spring-cloud-kubernetes-demo/Chart.yaml index 4a13d9d..4fc59fa 100644 --- a/helm/spring-cloud-kubernetes-demo/Chart.yaml +++ b/helm/spring-cloud-kubernetes-demo/Chart.yaml @@ -25,7 +25,7 @@ appVersion: "1.16.0" dependencies: - name: redis - version: "15.7.2" + version: "17.11.3" repository: "https://charts.bitnami.com/bitnami" - name: mongodb From bd6e6847c8c61e54da4ccb9f0208feac05673a1d Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sat, 10 Jun 2023 16:01:54 +0200 Subject: [PATCH 04/22] proper configuration for roles --- .../it/valeriovaudi/ui/UiApplication.java | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 55e977a..2364e8c 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -7,7 +7,18 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; +import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import java.util.*; +import java.util.stream.Collectors; @SpringBootApplication public class UiApplication { @@ -18,6 +29,37 @@ public static void main(String[] args) { } +class UserIntrospectorOidcUserService implements OAuth2UserService { + + private final OidcUserService delegate; + + public UserIntrospectorOidcUserService(OidcUserService delegate) { + this.delegate = delegate; + } + + @Override + public OidcUser loadUser(OidcUserRequest userRequest) { + OidcUser oidcUser = delegate.loadUser(userRequest); + Collection mappedAuthorities = authoritiesFor(oidcUser); + + return new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo()); + } + + + private Set authoritiesFor(OidcUser user) { + List authorities = authoritiesFrom(user); + return authorities.stream() + .map(SimpleGrantedAuthority::new) + .map(authority -> new OidcUserAuthority(authority.getAuthority(), user.getIdToken(), user.getUserInfo())) + .collect(Collectors.toSet()); + } + + private List authoritiesFrom(OidcUser oidcUser) { + List authoritiesClaim = (List) oidcUser.getClaimAsMap("realm_access").get("roles"); + return Optional.ofNullable(authoritiesClaim).orElse(Collections.emptyList()); + } +} + @Configuration(proxyBeanMethods = false) class SecurityConfig { @@ -34,16 +76,21 @@ public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws ); - http.oauth2Login(loginConfigurer -> loginConfigurer.defaultSuccessUrl("/index")); + http.oauth2Login(configurer -> + configurer.defaultSuccessUrl("/index").userInfoEndpoint(config -> + config.oidcUserService( + new UserIntrospectorOidcUserService(new OidcUserService())) + )); http.authorizeHttpRequests( auth -> auth - .requestMatchers("/index.html").hasRole("USER") - .requestMatchers("/messages.html").hasRole("USER") + .requestMatchers("/index.html").hasAuthority("USER") + .requestMatchers("/messages.html").hasAuthority("USER") .anyRequest().permitAll() ); + return http.build(); } From 855c9198a5c256565289be5fd1d11c20953f8062 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 11:25:09 +0200 Subject: [PATCH 05/22] proper configuration for roles --- ui/src/main/java/it/valeriovaudi/ui/UiApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 2364e8c..0a665c6 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -85,7 +85,7 @@ public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws http.authorizeHttpRequests( auth -> auth - .requestMatchers("/index.html").hasAuthority("USER") + .requestMatchers("/index.html").hasAuthority("ADMIN") .requestMatchers("/messages.html").hasAuthority("USER") .anyRequest().permitAll() ); From cfcc6d60797b05ac904acfe5774e8eff45432658 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 11:42:19 +0200 Subject: [PATCH 06/22] proper configuration for roles --- ui/src/main/java/it/valeriovaudi/ui/UiApplication.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 0a665c6..a311c55 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -5,9 +5,11 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; @@ -15,7 +17,6 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import java.util.*; import java.util.stream.Collectors; @@ -60,6 +61,7 @@ private List authoritiesFrom(OidcUser oidcUser) { } } +@EnableWebSecurity @Configuration(proxyBeanMethods = false) class SecurityConfig { From 26daf54d4314832c96755a6306bdf59b3874d491 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 12:01:44 +0200 Subject: [PATCH 07/22] proper configuration for roles --- ui/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/pom.xml b/ui/pom.xml index 8e7fed6..f32303a 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -24,6 +24,10 @@ org.springframework.boot spring-boot-starter-oauth2-client + + org.springframework.boot + spring-boot-starter-web + org.springframework.cloud spring-cloud-starter-bootstrap From a908df9e848fc98d004ba0e90e18ec9c6b3948ff Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 12:23:32 +0200 Subject: [PATCH 08/22] proper configuration for roles --- ui/pom.xml | 4 - .../it/valeriovaudi/ui/UiApplication.java | 97 +++++++++++++------ 2 files changed, 70 insertions(+), 31 deletions(-) diff --git a/ui/pom.xml b/ui/pom.xml index f32303a..8e7fed6 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -24,10 +24,6 @@ org.springframework.boot spring-boot-starter-oauth2-client - - org.springframework.boot - spring-boot-starter-web - org.springframework.cloud spring-cloud-starter-bootstrap diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index a311c55..c6c2204 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -4,19 +4,24 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.client.oidc.userinfo.OidcReactiveOAuth2UserService; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; +import org.springframework.security.oauth2.client.oidc.web.server.logout.OidcClientInitiatedServerLogoutSuccessHandler; +import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; +import org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; -import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler; +import reactor.core.publisher.Mono; import java.util.*; import java.util.stream.Collectors; @@ -30,7 +35,7 @@ public static void main(String[] args) { } -class UserIntrospectorOidcUserService implements OAuth2UserService { +class UserIntrospectorOidcUserService implements ReactiveOAuth2UserService { private final OidcUserService delegate; @@ -38,7 +43,14 @@ public UserIntrospectorOidcUserService(OidcUserService delegate) { this.delegate = delegate; } + + @Override + public Mono loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { + + return Mono.empty(); + } + public OidcUser loadUser(OidcUserRequest userRequest) { OidcUser oidcUser = delegate.loadUser(userRequest); Collection mappedAuthorities = authoritiesFor(oidcUser); @@ -61,39 +73,70 @@ private List authoritiesFrom(OidcUser oidcUser) { } } -@EnableWebSecurity +@EnableWebFluxSecurity @Configuration(proxyBeanMethods = false) class SecurityConfig { + private final ReactiveClientRegistrationRepository clientRegistrationRepository; + + SecurityConfig(ReactiveClientRegistrationRepository clientRegistrationRepository) { + this.clientRegistrationRepository = clientRegistrationRepository; + } @Bean - public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { - http.csrf(AbstractHttpConfigurer::disable); - http.headers(configurer -> configurer.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)); - - http.logout(logoutConfigurer -> - logoutConfigurer.deleteCookies("opbs") - .invalidateHttpSession(true) - .logoutSuccessUrl("/index") - ); + public ReactiveOAuth2UserService oidcUserService() { + final OidcReactiveOAuth2UserService delegate = new OidcReactiveOAuth2UserService(); + + return (userRequest) -> { + // Delegate to the default implementation for loading a user + return delegate.loadUser(userRequest) + .flatMap((oidcUser) -> { + List authorities = (List) oidcUser.getClaimAsMap("realm_access").get("roles"); + Set oidcAuthorities = authorities.stream() + .map(SimpleGrantedAuthority::new) + .map(authority -> new OidcUserAuthority(authority.getAuthority(), oidcUser.getIdToken(), oidcUser.getUserInfo())) + .collect(Collectors.toSet()); - http.oauth2Login(configurer -> - configurer.defaultSuccessUrl("/index").userInfoEndpoint(config -> - config.oidcUserService( - new UserIntrospectorOidcUserService(new OidcUserService())) - )); + return Mono.just(new DefaultOidcUser(oidcAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo())); + }); + }; - http.authorizeHttpRequests( + + } + + @Bean + public SecurityWebFilterChain defaultSecurityFilterChain(ServerHttpSecurity http) { + http.csrf(ServerHttpSecurity.CsrfSpec::disable); + http.headers(configurer -> configurer.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable)); + + http.logout(logoutSpec -> { + logoutSpec.logoutSuccessHandler(oidcLogoutSuccessHandler(clientRegistrationRepository)); + }); + + + http.oauth2Login(Customizer.withDefaults()); + + http.authorizeExchange( auth -> auth - .requestMatchers("/index.html").hasAuthority("ADMIN") - .requestMatchers("/messages.html").hasAuthority("USER") - .anyRequest().permitAll() + .pathMatchers("/index.html").hasAuthority("ADMIN") + .pathMatchers("/messages.html").hasAuthority("USER") + .anyExchange().permitAll() ); return http.build(); } -} \ No newline at end of file + private ServerLogoutSuccessHandler oidcLogoutSuccessHandler(ReactiveClientRegistrationRepository clientRegistrationRepository) { + OidcClientInitiatedServerLogoutSuccessHandler oidcLogoutSuccessHandler = + new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository); + + // Sets the location that the End-User's User Agent will be redirected to + // after the logout has been performed at the Provider + oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}"); + + return oidcLogoutSuccessHandler; + } +} From 6eec0dfaa3d60edb0e484b71be3a6facc4ae7a19 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 12:26:59 +0200 Subject: [PATCH 09/22] proper configuration for roles --- .../it/valeriovaudi/ui/UiApplication.java | 46 ++----------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index c6c2204..aab2da9 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -7,15 +7,12 @@ import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.client.oidc.userinfo.OidcReactiveOAuth2UserService; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; -import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; import org.springframework.security.oauth2.client.oidc.web.server.logout.OidcClientInitiatedServerLogoutSuccessHandler; import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; import org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; @@ -23,7 +20,8 @@ import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler; import reactor.core.publisher.Mono; -import java.util.*; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; @SpringBootApplication @@ -35,44 +33,6 @@ public static void main(String[] args) { } -class UserIntrospectorOidcUserService implements ReactiveOAuth2UserService { - - private final OidcUserService delegate; - - public UserIntrospectorOidcUserService(OidcUserService delegate) { - this.delegate = delegate; - } - - - - @Override - public Mono loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { - - return Mono.empty(); - } - - public OidcUser loadUser(OidcUserRequest userRequest) { - OidcUser oidcUser = delegate.loadUser(userRequest); - Collection mappedAuthorities = authoritiesFor(oidcUser); - - return new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo()); - } - - - private Set authoritiesFor(OidcUser user) { - List authorities = authoritiesFrom(user); - return authorities.stream() - .map(SimpleGrantedAuthority::new) - .map(authority -> new OidcUserAuthority(authority.getAuthority(), user.getIdToken(), user.getUserInfo())) - .collect(Collectors.toSet()); - } - - private List authoritiesFrom(OidcUser oidcUser) { - List authoritiesClaim = (List) oidcUser.getClaimAsMap("realm_access").get("roles"); - return Optional.ofNullable(authoritiesClaim).orElse(Collections.emptyList()); - } -} - @EnableWebFluxSecurity @Configuration(proxyBeanMethods = false) class SecurityConfig { @@ -113,7 +73,7 @@ public SecurityWebFilterChain defaultSecurityFilterChain(ServerHttpSecurity http http.logout(logoutSpec -> { logoutSpec.logoutSuccessHandler(oidcLogoutSuccessHandler(clientRegistrationRepository)); }); - +˚ http.oauth2Login(Customizer.withDefaults()); From db5b5f05af7d12e24ace940126df0d727bb355f9 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 12:27:48 +0200 Subject: [PATCH 10/22] proper configuration for roles --- ui/src/main/java/it/valeriovaudi/ui/UiApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index aab2da9..97206b8 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -73,7 +73,7 @@ public SecurityWebFilterChain defaultSecurityFilterChain(ServerHttpSecurity http http.logout(logoutSpec -> { logoutSpec.logoutSuccessHandler(oidcLogoutSuccessHandler(clientRegistrationRepository)); }); -˚ + http.oauth2Login(Customizer.withDefaults()); From e7e7460a4862c89540d1c6b3f31ca97b5ee48d0e Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 12:28:05 +0200 Subject: [PATCH 11/22] proper configuration for roles --- ui/src/main/java/it/valeriovaudi/ui/UiApplication.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 97206b8..030ccf6 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -80,8 +80,8 @@ public SecurityWebFilterChain defaultSecurityFilterChain(ServerHttpSecurity http http.authorizeExchange( auth -> auth - .pathMatchers("/index.html").hasAuthority("ADMIN") - .pathMatchers("/messages.html").hasAuthority("USER") + .pathMatchers("/index.html").hasAuthority("USER") + .pathMatchers("/messages.html").hasAuthority("ADMIN") .anyExchange().permitAll() ); From 4307807bc58d1a1306eaf558d0a6a9d8c89888e7 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 12:35:52 +0200 Subject: [PATCH 12/22] proper configuration for roles --- ui/src/main/java/it/valeriovaudi/ui/UiApplication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 030ccf6..146a486 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -58,6 +58,7 @@ public ReactiveOAuth2UserService oidcUserService() { .map(authority -> new OidcUserAuthority(authority.getAuthority(), oidcUser.getIdToken(), oidcUser.getUserInfo())) .collect(Collectors.toSet()); + System.out.println(oidcAuthorities); return Mono.just(new DefaultOidcUser(oidcAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo())); }); }; From 9e27a522f961f8c6ba3e38c9fcd284a2c99bc803 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 12:57:06 +0200 Subject: [PATCH 13/22] post logout --- .../templates/ui-interface.yml | 2 ++ helm/spring-cloud-kubernetes-demo/values.yaml | 2 +- .../it/valeriovaudi/ui/UiApplication.java | 24 +++++++++---------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml b/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml index c4170f8..caf2699 100644 --- a/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml +++ b/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml @@ -13,6 +13,8 @@ data: redis: host: {{ .Release.Namespace }}-redis-master + postLogoutUrl: {{ .Values.ui.postLogoutUrl }} + security: oauth2: client: diff --git a/helm/spring-cloud-kubernetes-demo/values.yaml b/helm/spring-cloud-kubernetes-demo/values.yaml index 5ecc82f..bd3d95d 100644 --- a/helm/spring-cloud-kubernetes-demo/values.yaml +++ b/helm/spring-cloud-kubernetes-demo/values.yaml @@ -21,7 +21,7 @@ keycloak: clientSecret: xxx ui: - baseUrl: http://localhost:8080 + postLogoutUrl: http://localhost:8080 replicas: 2 image: pullPolicy: Always diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 146a486..65036cd 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -1,5 +1,6 @@ package it.valeriovaudi.ui; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @@ -67,37 +68,36 @@ public ReactiveOAuth2UserService oidcUserService() { } @Bean - public SecurityWebFilterChain defaultSecurityFilterChain(ServerHttpSecurity http) { + public SecurityWebFilterChain defaultSecurityFilterChain( + @Value("${postLogoutUrl}") String postLogoutUrl, + ServerHttpSecurity http) { http.csrf(ServerHttpSecurity.CsrfSpec::disable); http.headers(configurer -> configurer.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable)); + http.oauth2Login(Customizer.withDefaults()); http.logout(logoutSpec -> { - logoutSpec.logoutSuccessHandler(oidcLogoutSuccessHandler(clientRegistrationRepository)); + logoutSpec.logoutSuccessHandler(oidcLogoutSuccessHandler(postLogoutUrl,clientRegistrationRepository)); }); - - http.oauth2Login(Customizer.withDefaults()); - http.authorizeExchange( auth -> auth + .pathMatchers("/index").hasAuthority("USER") .pathMatchers("/index.html").hasAuthority("USER") .pathMatchers("/messages.html").hasAuthority("ADMIN") .anyExchange().permitAll() ); - return http.build(); } - private ServerLogoutSuccessHandler oidcLogoutSuccessHandler(ReactiveClientRegistrationRepository clientRegistrationRepository) { + private ServerLogoutSuccessHandler oidcLogoutSuccessHandler( + String postLogoutUrl, + ReactiveClientRegistrationRepository clientRegistrationRepository + ) { OidcClientInitiatedServerLogoutSuccessHandler oidcLogoutSuccessHandler = new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository); - - // Sets the location that the End-User's User Agent will be redirected to - // after the logout has been performed at the Provider - oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}"); - + oidcLogoutSuccessHandler.setPostLogoutRedirectUri(postLogoutUrl); return oidcLogoutSuccessHandler; } } From 501a55c2cc9f1e4e8ae98a31d372e7fe89fd6cd5 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 13:00:36 +0200 Subject: [PATCH 14/22] post logout --- ui/src/main/java/it/valeriovaudi/ui/UiApplication.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 65036cd..616fb93 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -58,13 +58,10 @@ public ReactiveOAuth2UserService oidcUserService() { .map(SimpleGrantedAuthority::new) .map(authority -> new OidcUserAuthority(authority.getAuthority(), oidcUser.getIdToken(), oidcUser.getUserInfo())) .collect(Collectors.toSet()); - - System.out.println(oidcAuthorities); return Mono.just(new DefaultOidcUser(oidcAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo())); }); }; - } @Bean @@ -76,7 +73,7 @@ public SecurityWebFilterChain defaultSecurityFilterChain( http.oauth2Login(Customizer.withDefaults()); http.logout(logoutSpec -> { - logoutSpec.logoutSuccessHandler(oidcLogoutSuccessHandler(postLogoutUrl,clientRegistrationRepository)); + logoutSpec.logoutSuccessHandler(oidcLogoutSuccessHandler(postLogoutUrl, clientRegistrationRepository)); }); http.authorizeExchange( From a1a6ae9de7ba3729507b5a896e832e90e09fb0a4 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 13:35:38 +0200 Subject: [PATCH 15/22] post logout --- helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml b/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml index caf2699..bb291c8 100644 --- a/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml +++ b/helm/spring-cloud-kubernetes-demo/templates/ui-interface.yml @@ -5,6 +5,7 @@ metadata: namespace: {{ .Release.Namespace }} data: application.yaml: |- + postLogoutUrl: {{ .Values.ui.postLogoutUrl }} server: forward-headers-strategy: framework @@ -13,7 +14,6 @@ data: redis: host: {{ .Release.Namespace }}-redis-master - postLogoutUrl: {{ .Values.ui.postLogoutUrl }} security: oauth2: From 94cbb0bbf6fa72ad17770e872d331e762135df23 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 14:11:17 +0200 Subject: [PATCH 16/22] post logout --- ui/src/main/resources/bootstrap.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/src/main/resources/bootstrap.yml b/ui/src/main/resources/bootstrap.yml index 82ea3f3..5346d26 100644 --- a/ui/src/main/resources/bootstrap.yml +++ b/ui/src/main/resources/bootstrap.yml @@ -1,4 +1,7 @@ spring: + config: + import: kubernetes + application: name: ui-interface cloud: From e91f6ce51ddf482decc8ac4660c8477f7a85f1a5 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 14:15:37 +0200 Subject: [PATCH 17/22] post logout --- ui/pom.xml | 8 ++++---- ui/src/main/resources/bootstrap.yml | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/ui/pom.xml b/ui/pom.xml index 8e7fed6..0ed1064 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -24,10 +24,10 @@ org.springframework.boot spring-boot-starter-oauth2-client - - org.springframework.cloud - spring-cloud-starter-bootstrap - + + + + io.micrometer micrometer-tracing-bridge-brave diff --git a/ui/src/main/resources/bootstrap.yml b/ui/src/main/resources/bootstrap.yml index 5346d26..82ea3f3 100644 --- a/ui/src/main/resources/bootstrap.yml +++ b/ui/src/main/resources/bootstrap.yml @@ -1,7 +1,4 @@ spring: - config: - import: kubernetes - application: name: ui-interface cloud: From ed5c7c5541f84df964f073e10386611bd2834f75 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 14:18:48 +0200 Subject: [PATCH 18/22] post logout --- ui/pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/pom.xml b/ui/pom.xml index 0ed1064..8e7fed6 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -24,10 +24,10 @@ org.springframework.boot spring-boot-starter-oauth2-client - - - - + + org.springframework.cloud + spring-cloud-starter-bootstrap + io.micrometer micrometer-tracing-bridge-brave From 8636238def1b46750bae834d8ceaef8ec4ec503b Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 14:21:52 +0200 Subject: [PATCH 19/22] config --- ui/src/main/resources/bootstrap.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/src/main/resources/bootstrap.yml b/ui/src/main/resources/bootstrap.yml index 82ea3f3..01713fd 100644 --- a/ui/src/main/resources/bootstrap.yml +++ b/ui/src/main/resources/bootstrap.yml @@ -1,4 +1,6 @@ spring: + config: + import: "kubernetes:" application: name: ui-interface cloud: From 23be28179afa483aeab132f39782879719fe2b82 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 14:28:42 +0200 Subject: [PATCH 20/22] config --- ui/src/main/resources/bootstrap.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/main/resources/bootstrap.yml b/ui/src/main/resources/bootstrap.yml index 01713fd..469bf2e 100644 --- a/ui/src/main/resources/bootstrap.yml +++ b/ui/src/main/resources/bootstrap.yml @@ -1,6 +1,6 @@ spring: config: - import: "kubernetes:" + import: "kubernetes:ui-interface" application: name: ui-interface cloud: From 95cf9f0fe1a475283eb943ee820fd32d1c7d47f0 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 14:33:21 +0200 Subject: [PATCH 21/22] config --- ui/src/main/resources/bootstrap.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui/src/main/resources/bootstrap.yml b/ui/src/main/resources/bootstrap.yml index 469bf2e..82ea3f3 100644 --- a/ui/src/main/resources/bootstrap.yml +++ b/ui/src/main/resources/bootstrap.yml @@ -1,6 +1,4 @@ spring: - config: - import: "kubernetes:ui-interface" application: name: ui-interface cloud: From f41927fa2ffd0c013e61ac99862170ff990a1557 Mon Sep 17 00:00:00 2001 From: mrflick72 Date: Sun, 11 Jun 2023 15:19:26 +0200 Subject: [PATCH 22/22] config --- ui/src/main/java/it/valeriovaudi/ui/UiApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java index 616fb93..a6f0ba5 100644 --- a/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java +++ b/ui/src/main/java/it/valeriovaudi/ui/UiApplication.java @@ -79,7 +79,7 @@ public SecurityWebFilterChain defaultSecurityFilterChain( http.authorizeExchange( auth -> auth - .pathMatchers("/index").hasAuthority("USER") + .pathMatchers("/").hasAuthority("USER") .pathMatchers("/index.html").hasAuthority("USER") .pathMatchers("/messages.html").hasAuthority("ADMIN") .anyExchange().permitAll()