diff --git a/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/AuthorizationProperties.java b/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/AuthorizationProperties.java index 8efea5f00e..380334db28 100644 --- a/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/AuthorizationProperties.java +++ b/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/AuthorizationProperties.java @@ -30,24 +30,27 @@ */ public class AuthorizationProperties { + public static final String FRONTEND_LOGIN_URL = "/dashboard/index.html#/authentication-required"; private String externalAuthoritiesUrl; private List rules = new ArrayList<>(); private String dashboardUrl = "/dashboard"; - private String loginUrl = "/#/login"; + private String loginUrl = "/login"; - private String loginProcessingUrl = "/login"; + private String loginSuccessUrl = dashboardUrl; private String logoutUrl = "/logout"; - private String logoutSuccessUrl = "/logout-success.html"; + private String logoutSuccessUrl = dashboardUrl + "/logout-success-oauth.html"; private List permitAllPaths = new ArrayList<>(); private List authenticatedPaths = new ArrayList<>(); + private List anonymousPaths = new ArrayList<>(0); + /** * Role-mapping configuration per OAuth2 provider. */ @@ -91,12 +94,12 @@ public void setLoginUrl(String loginUrl) { this.loginUrl = loginUrl; } - public String getLoginProcessingUrl() { - return loginProcessingUrl; + public String getLoginSuccessUrl() { + return loginSuccessUrl; } - public void setLoginProcessingUrl(String loginProcessingUrl) { - this.loginProcessingUrl = loginProcessingUrl; + public void setLoginSuccessUrl(String loginSuccessUrl) { + this.loginSuccessUrl = loginSuccessUrl; } public String getLogoutUrl() { @@ -131,6 +134,14 @@ public void setAuthenticatedPaths(List authenticatedPaths) { this.authenticatedPaths = authenticatedPaths; } + public List getAnonymousPaths() { + return anonymousPaths; + } + + public void setAnonymousPaths(List anonymousPaths) { + this.anonymousPaths = anonymousPaths; + } + public void setDefaultProviderId(String defaultProviderId) { this.defaultProviderId = defaultProviderId; } diff --git a/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/OAuthSecurityConfiguration.java b/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/OAuthSecurityConfiguration.java index d10b25a9cd..062da219ce 100644 --- a/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/OAuthSecurityConfiguration.java +++ b/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/OAuthSecurityConfiguration.java @@ -216,28 +216,45 @@ protected void configure(HttpSecurity http) throws Exception { http.addFilter(basicAuthenticationFilter); } + // Anonymous paths for the login page + this.authorizationProperties.getAnonymousPaths().add(authorizationProperties.getLoginUrl()); + this.authorizationProperties.getAnonymousPaths().add("/login"); + + // All paths should be available only for authenticated users this.authorizationProperties.getAuthenticatedPaths().add("/"); - this.authorizationProperties.getAuthenticatedPaths() - .add(dashboard(authorizationProperties, "/**")); - this.authorizationProperties.getAuthenticatedPaths() - .add(this.authorizationProperties.getDashboardUrl()); - this.authorizationProperties.getPermitAllPaths() - .add(this.authorizationProperties.getDashboardUrl()); - this.authorizationProperties.getPermitAllPaths() - .add(dashboard(authorizationProperties, "/**")); - ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry security = - - http.authorizeRequests() - .antMatchers(this.authorizationProperties.getPermitAllPaths() - .toArray(new String[0])) - .permitAll() - .antMatchers(this.authorizationProperties.getAuthenticatedPaths() - .toArray(new String[0])) - .authenticated(); + this.authorizationProperties.getAuthenticatedPaths().add(this.authorizationProperties.getDashboardUrl()); + this.authorizationProperties.getAuthenticatedPaths().add(dashboard(authorizationProperties, "/**")); + + // Permit for all users as the visibility is managed through roles + this.authorizationProperties.getPermitAllPaths().add(this.authorizationProperties.getDashboardUrl()); + this.authorizationProperties.getPermitAllPaths().add(dashboard(authorizationProperties, "/**")); + + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry security; + + if (AuthorizationProperties.FRONTEND_LOGIN_URL.equals(this.authorizationProperties.getLoginUrl())) { + security = + http.authorizeRequests() + .antMatchers(this.authorizationProperties.getAuthenticatedPaths().toArray(new String[0])) + .authenticated() + .antMatchers(this.authorizationProperties.getPermitAllPaths().toArray(new String[0])) + .permitAll() + .antMatchers(this.authorizationProperties.getAnonymousPaths().toArray(new String[0])) + .anonymous(); + + } else { + security = + http.authorizeRequests() + .antMatchers(this.authorizationProperties.getPermitAllPaths().toArray(new String[0])) + .permitAll() + .antMatchers(this.authorizationProperties.getAuthenticatedPaths().toArray(new String[0])) + .authenticated() + .antMatchers(this.authorizationProperties.getAnonymousPaths().toArray(new String[0])) + .anonymous(); + } + security = SecurityConfigUtils.configureSimpleSecurity(security, this.authorizationProperties); security.anyRequest().denyAll(); - http.httpBasic().and() .logout() .logoutSuccessHandler(logoutSuccessHandler) @@ -248,11 +265,13 @@ protected void configure(HttpSecurity http) throws Exception { new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")) .defaultAuthenticationEntryPointFor( - new LoginUrlAuthenticationEntryPoint(this.authorizationProperties.getLoginProcessingUrl()), + new LoginUrlAuthenticationEntryPoint(authorizationProperties.getLoginUrl()), textHtmlMatcher) .defaultAuthenticationEntryPointFor(basicAuthenticationEntryPoint, AnyRequestMatcher.INSTANCE); - http.oauth2Login().userInfoEndpoint() + http.oauth2Login() + .defaultSuccessUrl(authorizationProperties.getLoginSuccessUrl()) + .userInfoEndpoint() .userService(this.plainOauth2UserService) .oidcUserService(this.oidcUserService); @@ -401,7 +420,7 @@ protected LogoutSuccessHandler logoutSuccessHandler(AuthorizationProperties auth OAuth2TokenUtilsService oauth2TokenUtilsService) { AccessTokenClearingLogoutSuccessHandler logoutSuccessHandler = new AccessTokenClearingLogoutSuccessHandler(oauth2TokenUtilsService); - logoutSuccessHandler.setDefaultTargetUrl(dashboard(authorizationProperties, "/logout-success-oauth.html")); + logoutSuccessHandler.setDefaultTargetUrl(authorizationProperties.getLogoutSuccessUrl()); return logoutSuccessHandler; } } diff --git a/spring-cloud-dataflow-rest-resource/src/main/java/org/springframework/cloud/dataflow/rest/resource/about/SecurityInfo.java b/spring-cloud-dataflow-rest-resource/src/main/java/org/springframework/cloud/dataflow/rest/resource/about/SecurityInfo.java index 42fa84f9e9..81c9b1dae2 100644 --- a/spring-cloud-dataflow-rest-resource/src/main/java/org/springframework/cloud/dataflow/rest/resource/about/SecurityInfo.java +++ b/spring-cloud-dataflow-rest-resource/src/main/java/org/springframework/cloud/dataflow/rest/resource/about/SecurityInfo.java @@ -35,6 +35,8 @@ public class SecurityInfo { private List roles = new ArrayList<>(0); + private List clientRegistrations = new ArrayList<>(0); + /** * Default constructor for serialization frameworks. */ @@ -85,6 +87,18 @@ public void setRoles(List roles) { this.roles = roles; } + /** + * + * @return List of all available client registrations + */ + public List getClientRegistrations() { + return clientRegistrations; + } + + public void setClientRegistrations(List clientRegistrations) { + this.clientRegistrations = clientRegistrations; + } + /** * @param role Adds the role to {@link #roles} * @return the security related meta-information diff --git a/spring-cloud-dataflow-rest-resource/src/main/java/org/springframework/cloud/dataflow/rest/resource/security/SecurityInfoResource.java b/spring-cloud-dataflow-rest-resource/src/main/java/org/springframework/cloud/dataflow/rest/resource/security/SecurityInfoResource.java index f9e36d621a..e3329abb08 100644 --- a/spring-cloud-dataflow-rest-resource/src/main/java/org/springframework/cloud/dataflow/rest/resource/security/SecurityInfoResource.java +++ b/spring-cloud-dataflow-rest-resource/src/main/java/org/springframework/cloud/dataflow/rest/resource/security/SecurityInfoResource.java @@ -37,6 +37,8 @@ public class SecurityInfoResource extends RepresentationModel { private List roles = new ArrayList<>(0); + private List clientRegistrations = new ArrayList<>(0); + /** * Default constructor for serialization frameworks. */ @@ -87,6 +89,18 @@ public void setRoles(List roles) { this.roles = roles; } + /** + * + * @return List of all available client registrations + */ + public List getClientRegistrations() { + return clientRegistrations; + } + + public void setClientRegistrations(List clientRegistrations) { + this.clientRegistrations = clientRegistrations; + } + /** * @param role Adds the role to {@link #roles} * @return the resource with an additional role diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java index a638efc232..f7a320802e 100644 --- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java +++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.concurrent.ForkJoinPool; +import javax.annotation.Nullable; + import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; @@ -33,6 +35,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.client.RestTemplateBuilder; @@ -144,7 +147,6 @@ import org.springframework.hateoas.server.core.AnnotationLinkRelationProvider; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.lang.Nullable; import org.springframework.scheduling.concurrent.ForkJoinPoolFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.client.RestTemplate; @@ -203,11 +205,12 @@ public AboutController aboutController(ObjectProvider streamDepl VersionInfoProperties versionInfoProperties, SecurityStateBean securityStateBean, DataflowMetricsProperties monitoringDashboardInfoProperties, - ObjectProvider gitInfoContributor, + @Nullable OAuth2ClientProperties oAuth2ClientProperties, + ObjectProvider gitInfoContributor, ObjectProvider buildInfoContributor) { return new AboutController(streamDeployer.getIfAvailable(), launcherRepository.getIfAvailable(), featuresProperties, versionInfoProperties, securityStateBean, monitoringDashboardInfoProperties, - gitInfoContributor, buildInfoContributor); + oAuth2ClientProperties, gitInfoContributor, buildInfoContributor); } @Bean @@ -562,8 +565,9 @@ public SecurityStateBean securityStateBean() { } @Bean - public SecurityController securityController(SecurityStateBean securityStateBean) { - return new SecurityController(securityStateBean); + public SecurityController securityController(SecurityStateBean securityStateBean, + @Nullable OAuth2ClientProperties oAuth2ClientProperties) { + return new SecurityController(securityStateBean, oAuth2ClientProperties); } @Bean diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/AboutController.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/AboutController.java index bd25aa0fcd..3df7daa5d6 100644 --- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/AboutController.java +++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/AboutController.java @@ -18,6 +18,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; + +import javax.annotation.Nullable; + import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; @@ -25,6 +29,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; import org.springframework.boot.actuate.info.BuildInfoContributor; import org.springframework.boot.actuate.info.GitInfoContributor; import org.springframework.boot.actuate.info.Info; @@ -56,6 +61,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; @@ -93,6 +99,8 @@ public class AboutController { private final SecurityStateBean securityStateBean; + private final OAuth2ClientProperties oAuth2ClientProperties; + @Value("${security.oauth2.client.client-id:#{null}}") private String oauthClientId; @@ -112,13 +120,15 @@ public class AboutController { @Deprecated public AboutController(StreamDeployer streamDeployer, LauncherRepository launcherRepository, FeaturesProperties featuresProperties, - VersionInfoProperties versionInfoProperties, SecurityStateBean securityStateBean, DataflowMetricsProperties monitoringProperties) { + VersionInfoProperties versionInfoProperties, SecurityStateBean securityStateBean, DataflowMetricsProperties monitoringProperties, + @Nullable OAuth2ClientProperties oAuth2ClientProperties) { this.streamDeployer = streamDeployer; this.launcherRepository = launcherRepository; this.featuresProperties = featuresProperties; this.versionInfoProperties = versionInfoProperties; this.securityStateBean = securityStateBean; this.dataflowMetricsProperties = monitoringProperties; + this.oAuth2ClientProperties = oAuth2ClientProperties; } public AboutController(StreamDeployer streamDeployer, LauncherRepository launcherRepository, FeaturesProperties featuresProperties, @@ -161,7 +171,7 @@ public AboutResource getAboutResource() { if (authenticationEnabled && SecurityContextHolder.getContext() != null) { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)) { + if (!(authentication instanceof AnonymousAuthenticationToken) && authentication != null) { securityInfo.setAuthenticated(authentication.isAuthenticated()); securityInfo.setUsername(authentication.getName()); @@ -170,6 +180,16 @@ public AboutResource getAboutResource() { securityInfo.addRole(grantedAuthority.getAuthority()); } } + + // Apply all client registrations to security infos which are based on authorization_code + if(oAuth2ClientProperties != null) { + List authorizationCodeBasedClientRegistrations = oAuth2ClientProperties.getRegistration() + .entrySet() + .stream() + .filter(entry -> AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equals(entry.getValue().getAuthorizationGrantType())) + .map(Map.Entry::getKey).collect(Collectors.toList()); + securityInfo.setClientRegistrations(authorizationCodeBasedClientRegistrations); + } } aboutResource.setSecurityInfo(securityInfo); diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/security/SecurityController.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/security/SecurityController.java index 7651ca1c78..dd204ce82c 100644 --- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/security/SecurityController.java +++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/security/SecurityController.java @@ -16,7 +16,14 @@ package org.springframework.cloud.dataflow.server.controller.security; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.annotation.Nullable; + import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; import org.springframework.cloud.common.security.support.SecurityStateBean; import org.springframework.cloud.dataflow.rest.resource.security.SecurityInfoResource; import org.springframework.hateoas.server.ExposesResourceFor; @@ -25,6 +32,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @@ -52,8 +60,11 @@ public class SecurityController { @Value("${security.oauth2.client.client-id:#{null}}") private String oauthClientId; - public SecurityController(SecurityStateBean securityStateBean) { + private OAuth2ClientProperties oAuth2ClientProperties; + + public SecurityController(SecurityStateBean securityStateBean, @Nullable OAuth2ClientProperties oAuth2ClientProperties) { this.securityStateBean = securityStateBean; + this.oAuth2ClientProperties = oAuth2ClientProperties; } /** @@ -74,18 +85,25 @@ public SecurityInfoResource getSecurityInfo() { if (authenticationEnabled && SecurityContextHolder.getContext() != null) { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)) { + if (!(authentication instanceof AnonymousAuthenticationToken) && authentication != null) { securityInfo.setAuthenticated(authentication.isAuthenticated()); securityInfo.setUsername(authentication.getName()); for (GrantedAuthority authority : authentication.getAuthorities()) { securityInfo.addRole(authority.getAuthority()); } + } + // Apply all client registrations to security infos which are based on authorization_code + if(oAuth2ClientProperties != null) { + List authorizationCodeBasedClientRegistrations = oAuth2ClientProperties.getRegistration() + .entrySet() + .stream() + .filter(entry -> AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equals(entry.getValue().getAuthorizationGrantType())) + .map(Map.Entry::getKey).collect(Collectors.toList()); + securityInfo.setClientRegistrations(authorizationCodeBasedClientRegistrations); } } - return securityInfo; } - } diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java index 13013752d5..a334dfd2f9 100644 --- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java +++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java @@ -25,6 +25,7 @@ import java.util.Optional; import java.util.concurrent.ForkJoinPool; +import javax.annotation.Nullable; import javax.sql.DataSource; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; @@ -42,6 +43,7 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -769,12 +771,13 @@ public TaskPlatform taskPlatform(Scheduler scheduler) { @Bean public AboutController aboutController( - VersionInfoProperties versionInfoProperties, - FeaturesProperties featuresProperties, StreamDeployer streamDeployer, - DataflowMetricsProperties monitoringDashboardInfoProperties, - ObjectProvider gitInfoContributor, - ObjectProvider buildInfoContributor - ) { + VersionInfoProperties versionInfoProperties, + FeaturesProperties featuresProperties, StreamDeployer streamDeployer, + DataflowMetricsProperties monitoringDashboardInfoProperties, + @Nullable OAuth2ClientProperties oAuth2ClientProperties, + ObjectProvider gitInfoContributor, + ObjectProvider buildInfoContributor + ) { Launcher launcher = mock(Launcher.class); TaskLauncher taskLauncher = mock(TaskLauncher.class); @@ -796,7 +799,7 @@ public AboutController aboutController( return new AboutController(streamDeployer, launcherRepository, featuresProperties, versionInfoProperties, mock(SecurityStateBean.class), monitoringDashboardInfoProperties, - gitInfoContributor, buildInfoContributor); + oAuth2ClientProperties, gitInfoContributor, buildInfoContributor); } diff --git a/spring-cloud-dataflow-shell-core/src/test/resources/org/springframework/cloud/dataflow/shell/command/ConfigCommandTests-testInfo.txt b/spring-cloud-dataflow-shell-core/src/test/resources/org/springframework/cloud/dataflow/shell/command/ConfigCommandTests-testInfo.txt index 2260f15994..e902017439 100644 --- a/spring-cloud-dataflow-shell-core/src/test/resources/org/springframework/cloud/dataflow/shell/command/ConfigCommandTests-testInfo.txt +++ b/spring-cloud-dataflow-shell-core/src/test/resources/org/springframework/cloud/dataflow/shell/command/ConfigCommandTests-testInfo.txt @@ -9,8 +9,9 @@ ╟─────────────────┼─────────────────────────────────────╢ ║ Versions │Foo Core: 1.2.3.BUILD-SNAPSHOT ║ ╟─────────────────┼─────────────────────────────────────╢ -║ Security │ Authenticated: false ║ -║ │Authentication Enabled: true ║ +║ │ Authenticated: false ║ +║ Security │Authentication Enabled: true ║ +║ │ Client Registrations: [] ║ ╟─────────────────┼─────────────────────────────────────╢ ║ │Deployer Implementation Version: null║ ║ │ Deployer Name: null║ diff --git a/spring-cloud-skipper/spring-cloud-skipper-server-core/src/main/java/org/springframework/cloud/skipper/server/config/security/SkipperOAuthSecurityConfiguration.java b/spring-cloud-skipper/spring-cloud-skipper-server-core/src/main/java/org/springframework/cloud/skipper/server/config/security/SkipperOAuthSecurityConfiguration.java index 1aadf32bb9..8973e923df 100644 --- a/spring-cloud-skipper/spring-cloud-skipper-server-core/src/main/java/org/springframework/cloud/skipper/server/config/security/SkipperOAuthSecurityConfiguration.java +++ b/spring-cloud-skipper/spring-cloud-skipper-server-core/src/main/java/org/springframework/cloud/skipper/server/config/security/SkipperOAuthSecurityConfiguration.java @@ -62,26 +62,46 @@ protected void configure(HttpSecurity http) throws Exception { http.addFilter(basicAuthenticationFilter); } - getAuthorizationProperties().getAuthenticatedPaths() - .add(dashboard(getAuthorizationProperties(), "/**")); - getAuthorizationProperties().getAuthenticatedPaths() - .add(dashboard(getAuthorizationProperties(), "")); - - ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry security = - http.authorizeRequests() - .antMatchers(getAuthorizationProperties().getPermitAllPaths() - .toArray(new String[0])) - .permitAll() - .antMatchers(getAuthorizationProperties().getAuthenticatedPaths() - .toArray(new String[0])) - .authenticated(); + getAuthorizationProperties().getAnonymousPaths().add(authorizationProperties.getLoginUrl()); + + // All paths should be available only for authenticated users + getAuthorizationProperties().getAuthenticatedPaths().add("/"); + getAuthorizationProperties().getAuthenticatedPaths().add(this.authorizationProperties.getDashboardUrl()); + getAuthorizationProperties().getAuthenticatedPaths().add(dashboard(authorizationProperties, "/**")); + + // Permit for all users as the visibility is managed through roles + getAuthorizationProperties().getPermitAllPaths().add(this.authorizationProperties.getDashboardUrl()); + getAuthorizationProperties().getPermitAllPaths().add(dashboard(authorizationProperties, "/**")); + + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry security; + + if (AuthorizationProperties.FRONTEND_LOGIN_URL.equals(this.authorizationProperties.getLoginUrl())) { + security = + http.authorizeRequests() + .antMatchers(this.authorizationProperties.getAuthenticatedPaths().toArray(new String[0])) + .authenticated() + .antMatchers(this.authorizationProperties.getPermitAllPaths().toArray(new String[0])) + .permitAll() + .antMatchers(this.authorizationProperties.getAnonymousPaths().toArray(new String[0])) + .anonymous(); + + } else { + security = + http.authorizeRequests() + .antMatchers(this.authorizationProperties.getPermitAllPaths().toArray(new String[0])) + .permitAll() + .antMatchers(this.authorizationProperties.getAuthenticatedPaths().toArray(new String[0])) + .authenticated() + .antMatchers(this.authorizationProperties.getAnonymousPaths().toArray(new String[0])) + .anonymous(); + } security = SecurityConfigUtils.configureSimpleSecurity(security, getAuthorizationProperties()); security.anyRequest().denyAll(); http.httpBasic().and() .logout() - .logoutSuccessUrl(dashboard(getAuthorizationProperties(), "/logout-success-oauth.html")) + .logoutSuccessUrl(getAuthorizationProperties().getLogoutSuccessUrl()) .and().csrf().disable() .exceptionHandling() .defaultAuthenticationEntryPointFor(basicAuthenticationEntryPoint, new AntPathRequestMatcher("/api/**"))