diff --git a/pom.xml b/pom.xml index d5414c64f..6e38c8388 100644 --- a/pom.xml +++ b/pom.xml @@ -592,7 +592,16 @@ spring-security-config ${spring.security.version} - + + org.springframework.security + spring-security-oauth2-client + ${spring.security.version} + + + org.springframework.security + spring-security-oauth2-jose + ${spring.security.version} + org.apache.logging.log4j diff --git a/src/main/java/de/rwth/idsg/steve/SteveConfiguration.java b/src/main/java/de/rwth/idsg/steve/SteveConfiguration.java index 7aeb2e911..291bd6ee0 100644 --- a/src/main/java/de/rwth/idsg/steve/SteveConfiguration.java +++ b/src/main/java/de/rwth/idsg/steve/SteveConfiguration.java @@ -95,6 +95,14 @@ public enum SteveConfiguration { .passwordEncoder(encoder) .userName(p.getString("auth.user")) .encodedPassword(encoder.encode(p.getString("auth.password"))) + .method(p.getOptionalString("auth.method")) + .oAuthAuthorizationUri(p.getOptionalString("auth.oauth2.authorization-uri")) + .oAuthClientId(p.getOptionalString("auth.oauth2.client-id")) + .oAuthClientSecret(p.getOptionalString("auth.oauth2.client-secret")) + .oAuthTokenUri(p.getOptionalString("auth.oauth2.token-uri")) + .oAuthJwkSetUri(p.getOptionalString("auth.oauth2.jwk-set-uri")) + .oAuthUserInfoUri(p.getOptionalString("auth.oauth2.user-info-uri")) + .oAuthLogoutUri(p.getOptionalString("auth.oauth2.logout-uri")) .build(); webApi = WebApi.builder() @@ -185,6 +193,14 @@ public static class DB { // Credentials for Web interface access @Builder @Getter public static class Auth { + private final String method; + private final String oAuthClientId; + private final String oAuthClientSecret; + private final String oAuthAuthorizationUri; + private final String oAuthTokenUri; + private final String oAuthUserInfoUri; + private final String oAuthJwkSetUri; + private final String oAuthLogoutUri; private final PasswordEncoder passwordEncoder; private final String userName; private final String encodedPassword; diff --git a/src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java b/src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java index 65c87d867..705a27659 100644 --- a/src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java +++ b/src/main/java/de/rwth/idsg/steve/config/SecurityConfiguration.java @@ -32,6 +32,9 @@ import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.DisabledException; +import org.springframework.security.config.Customizer; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; 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.configuration.WebSecurityCustomizer; @@ -44,6 +47,10 @@ import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.DelegatingPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; @@ -53,6 +60,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.Arrays; +import java.util.Objects; import static de.rwth.idsg.steve.SteveConfiguration.CONFIG; @@ -96,25 +105,54 @@ public WebSecurityCustomizer webSecurityCustomizer() { CONFIG.getCxfMapping() + "/**" ); } + @Bean + public ClientRegistrationRepository clientRegistrationRepository() { + if (CONFIG.getAuth().getMethod().equals("oauth2")){ + ClientRegistration registration = ClientRegistration.withRegistrationId("sso") + .clientId(CONFIG.getAuth().getOAuthClientId()) + .clientSecret(CONFIG.getAuth().getOAuthClientSecret()) + .authorizationUri(CONFIG.getAuth().getOAuthAuthorizationUri()) + .jwkSetUri(CONFIG.getAuth().getOAuthJwkSetUri()) + .userInfoUri(CONFIG.getAuth().getOAuthUserInfoUri()) + .scope("openid", "profile", "email") + .tokenUri(CONFIG.getAuth().getOAuthTokenUri()) + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) + .userNameAttributeName(IdTokenClaimNames.SUB) + .redirectUri("{baseUrl}/login/oauth2/code/sso") + .clientName("SSO") + .build(); + + return new InMemoryClientRegistrationRepository(registration); + } + return null; + } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { final String prefix = CONFIG.getSpringManagerMapping(); - return http - .authorizeHttpRequests( - req -> req.antMatchers(prefix + "/**").hasRole("ADMIN") - ) - .sessionManagement( - req -> req.invalidSessionUrl(prefix + "/signin") - ) - .formLogin( - req -> req.loginPage(prefix + "/signin").permitAll() - ) - .logout( - req -> req.logoutUrl(prefix + "/signout") - ) - .build(); + if (CONFIG.getAuth().getMethod().equals("oauth2")){ + return http.authorizeHttpRequests(req -> req.antMatchers(prefix + "/**").authenticated()).oauth2Login(Customizer.withDefaults()) + .logout( + req -> req.logoutUrl(prefix + "/signout") + ).build(); + } else { + return http + .authorizeHttpRequests( + req -> req.antMatchers(prefix + "/**").hasRole("ADMIN") + ) + .sessionManagement( + req -> req.invalidSessionUrl(prefix + "/signin") + ) + .formLogin( + req -> req.loginPage(prefix + "/signin").permitAll() + ) + .logout( + req -> req.logoutUrl(prefix + "/signout") + ) + .build(); + } } @Bean diff --git a/src/main/java/de/rwth/idsg/steve/web/controller/SignOutController.java b/src/main/java/de/rwth/idsg/steve/web/controller/SignOutController.java index 24150f2d6..15fd8d6bc 100644 --- a/src/main/java/de/rwth/idsg/steve/web/controller/SignOutController.java +++ b/src/main/java/de/rwth/idsg/steve/web/controller/SignOutController.java @@ -28,6 +28,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import static de.rwth.idsg.steve.SteveConfiguration.CONFIG; + /** * @author Sevket Goekay * @since 15.08.2014 @@ -42,6 +44,9 @@ public String signOut(HttpServletRequest request, HttpServletResponse response) .logout(request, response, null); new CookieClearingLogoutHandler(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY) .logout(request, response, null); + if (CONFIG.getAuth().getMethod().equals("oauth2")){ + return "redirect:" + CONFIG.getAuth().getOAuthLogoutUri(); + } return "redirect:/manager/signin"; } } diff --git a/src/main/resources/config/docker/main.properties b/src/main/resources/config/docker/main.properties index bd2387635..6196c0869 100644 --- a/src/main/resources/config/docker/main.properties +++ b/src/main/resources/config/docker/main.properties @@ -14,6 +14,14 @@ db.password = changeme # Credentials for Web interface access # +auth.method = oauth2 +auth.oauth2.client-id = Test +auth.oauth2.client-secret = Test +auth.oauth2.authorization-uri = https://sso/idp/profile/oidc/authorize +auth.oauth2.token-uri = https://sso/idp/profile/oidc/token +auth.oauth2.jwk-set-uri = https://sso/idp/profile/oidc/keyset +auth.oauth2.user-info-uri = https://sso/idp/profile/oidc/userinfo +auth.oauth2.logout-uri = https://sso/idp/profile/Logout auth.user = admin auth.password = 1234