package ru.ulstu.configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.oauth2.client.CommonOAuth2Provider; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import ru.ulstu.core.model.AuthFailureHandler; import ru.ulstu.core.navigation.Page; import ru.ulstu.user.model.UserRoleConstants; import ru.ulstu.user.service.UserService; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class); private static List clients = Arrays.asList("google"); private static final String CLIENT_PROPERTY_KEY = "spring.security.oauth2.client.registration."; @Autowired private Environment env; @Value("${server.http.port}") private int httpPort; @Value("${server.port}") private int httpsPort; private final UserService userService; private final BCryptPasswordEncoder bCryptPasswordEncoder; private final AuthenticationSuccessHandler authenticationSuccessHandler; private final LogoutSuccessHandler logoutSuccessHandler; private final ApplicationProperties applicationProperties; private final AuthenticationFailureHandler authenticationFailureHandler; public SecurityConfiguration(UserService userService, BCryptPasswordEncoder bCryptPasswordEncoder, AuthenticationSuccessHandler authenticationSuccessHandler, LogoutSuccessHandler logoutSuccessHandler, ApplicationProperties applicationProperties, AuthFailureHandler authenticationFailureHandler) { this.userService = userService; this.bCryptPasswordEncoder = bCryptPasswordEncoder; this.authenticationSuccessHandler = authenticationSuccessHandler; this.logoutSuccessHandler = logoutSuccessHandler; this.applicationProperties = applicationProperties; this.authenticationFailureHandler = authenticationFailureHandler; } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); if (applicationProperties.isDevMode()) { log.debug("Security disabled"); http.authorizeRequests() .anyRequest() .permitAll(); http.anonymous() .principal("admin") .authorities(UserRoleConstants.ADMIN); } else { http.authorizeRequests() .antMatchers("/login.xhtml", "/logout") .permitAll() .anyRequest() .authenticated() .antMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN) .and() .formLogin() .loginPage("/login.xhtml") .successHandler(authenticationSuccessHandler) .failureHandler(authenticationFailureHandler) .permitAll() .and() .oauth2Login() .loginPage("/login.xhtml") .authorizationEndpoint() .baseUri("/oauth2/authorize-client") .authorizationRequestRepository(authorizationRequestRepository()) .and() .tokenEndpoint() .accessTokenResponseClient(accessTokenResponseClient()) .and() .defaultSuccessUrl(Page.INDEX) .failureUrl("/loginFailure") .and() .logout() .logoutSuccessHandler(logoutSuccessHandler) .logoutSuccessUrl(Page.LOGOUT) .invalidateHttpSession(true) .clearAuthentication(true) .deleteCookies(Constants.COOKIES_NAME) .permitAll(); http.csrf().disable(); } if (applicationProperties.isUseHttps()) { http.portMapper() .http(httpPort) .mapsTo(httpsPort) .and() .requiresChannel() .anyRequest() .requiresSecure(); } } @Bean public AuthorizationRequestRepository authorizationRequestRepository() { return new HttpSessionOAuth2AuthorizationRequestRepository(); } @Bean public OAuth2AccessTokenResponseClient accessTokenResponseClient() { DefaultAuthorizationCodeTokenResponseClient accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient(); return accessTokenResponseClient; } //@Bean public ClientRegistrationRepository clientRegistrationRepository() { List registrations = clients.stream() .map(c -> getRegistration(c)) .filter(registration -> registration != null) .collect(Collectors.toList()); return new InMemoryClientRegistrationRepository(registrations); } private ClientRegistration getRegistration(String client) { String clientId = env.getProperty(CLIENT_PROPERTY_KEY + client + ".client-id"); if (clientId == null) { return null; } String clientSecret = env.getProperty(CLIENT_PROPERTY_KEY + client + ".client-secret"); if (client.equals("google")) { return CommonOAuth2Provider.GOOGLE.getBuilder(client) .clientId(clientId) .clientSecret(clientSecret) .build(); } return null; } @Override public void configure(WebSecurity web) { web.ignoring() .antMatchers("/css/**") .antMatchers("/javax.faces.resource/**") .antMatchers("/js/**") .antMatchers("/templates/**") .antMatchers("/webjars/**") .antMatchers("/img/**"); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { if (applicationProperties.isDevMode()) { return; } try { auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder); } catch (Exception e) { throw new BeanInitializationException("Security configuration failed", e); } } }