Java tutorial
/* * Copyright (C) 2016 Dominik Schadow, dominikschadow@gmail.com * * This file is part of the Application Intrusion Detection project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.dominikschadow.duke.encounters.config; import org.owasp.appsensor.integration.springsecurity.context.AppSensorSecurityContextRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices; import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; 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.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.client.OAuth2ClientContext; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter; import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.security.web.header.writers.StaticHeadersWriter; import org.springframework.web.filter.CompositeFilter; import javax.servlet.Filter; import javax.sql.DataSource; import java.util.ArrayList; import java.util.List; /** * Spring Security configuration file. * * @author Dominik Schadow */ @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) @EnableOAuth2Client @EnableAuthorizationServer @Order(6) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SecurityContextRepository securityContextRepository; @Autowired private DataSource dataSource; @Autowired private OAuth2ClientContext oauth2ClientContext; @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.authorizeRequests().antMatchers("/", "/register", "/encounters", "/search", "/error").permitAll() .antMatchers("/admin/**").hasRole("ADMIN").anyRequest().authenticated().and().formLogin() .loginPage("/login").defaultSuccessUrl("/account").permitAll().and().exceptionHandling() .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")).and().logout() .logoutSuccessUrl("/").permitAll().and().rememberMe().and().securityContext() .securityContextRepository(securityContextRepository).and().headers() .addHeaderWriter(new StaticHeadersWriter("Content-Security-Policy", "default-src 'self'")).and() .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class); // @formatter:on } @Bean public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(filter); registration.setOrder(-100); return registration; } @Bean @ConfigurationProperties("github") ClientResources github() { return new ClientResources(); } private Filter ssoFilter() { CompositeFilter filter = new CompositeFilter(); List<Filter> filters = new ArrayList<>(); filters.add(ssoFilter(github(), "/login/github")); filter.setFilters(filters); return filter; } private Filter ssoFilter(ClientResources client, String path) { OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationFilter = new OAuth2ClientAuthenticationProcessingFilter( path); OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext); oAuth2ClientAuthenticationFilter.setRestTemplate(oAuth2RestTemplate); UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(), client.getClient().getClientId()); tokenServices.setRestTemplate(oAuth2RestTemplate); oAuth2ClientAuthenticationFilter.setTokenServices(tokenServices); return oAuth2ClientAuthenticationFilter; } /** * BCryptPasswordEncoder constructor takes a work factor as first argument. The default is 10, the valid range is * 4 to 31. The amount of work increases exponentially. * * @return The PasswordEncoder to use for all dukeEncountersUser passwords */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(10); } @Override public void configure(WebSecurity web) { // @formatter:off web.ignoring().antMatchers("/css/**", "/img/**", "/webjars/**"); // @formatter:on } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder()); // @formatter:on } @Bean public SecurityContextRepository securityContextRepository() { return new AppSensorSecurityContextRepository(); } class ClientResources { private OAuth2ProtectedResourceDetails client = new AuthorizationCodeResourceDetails(); private ResourceServerProperties resource = new ResourceServerProperties(); public OAuth2ProtectedResourceDetails getClient() { return client; } public ResourceServerProperties getResource() { return resource; } } }