From b8b88a6879291be87ee5dd7900219dadb232dfba Mon Sep 17 00:00:00 2001 From: "fabio.formosa" Date: Sat, 2 May 2020 16:48:45 +0200 Subject: [PATCH] #6 added javadocs and moved packages --- .../DeprecatedWebSecurityConfig.java | 89 --------------- .../configuration/WebSecurityConfigJWT.java | 57 ++++------ .../helpers/LoginConfigurer.java | 12 -- .../helpers/impl/FormLoginConfig.java | 37 ------ .../controllers/AuthenticationController.java | 2 +- .../auth/JwtTokenAuthenticationFilter.java | 93 ---------------- .../security/helpers/LoginConfigurer.java | 21 ++++ .../impl}/AjaxAuthenticationFilter.java | 2 +- .../impl}/AnonAuthentication.java | 2 +- .../impl}/AuthenticationFailureHandler.java | 4 +- .../impl}/AuthenticationSuccessHandler.java | 4 +- .../{ => helpers/impl}/ComboEntryPoint.java | 2 +- .../helpers/impl/FormLoginConfig.java | 75 +++++++++++++ .../impl}/JwtAuthenticationFilter.java | 8 +- .../JwtAuthenticationSuccessHandler.java | 5 +- .../JwtAuthenticationSuccessHandlerImpl.java | 26 +++-- .../impl/JwtTokenAuthenticationFilter.java | 105 ++++++++++++++++++ .../impl}/JwtTokenBasedAuthentication.java | 2 +- .../{ => helpers/impl}/JwtTokenHelper.java | 11 +- .../JwtUsernamePasswordFiterLoginConfig.java} | 22 ++-- .../{auth => helpers/impl}/LogoutSuccess.java | 3 +- .../impl/QuartzManagerHttpSecurity.java | 31 +++--- .../impl}/RESTRequestMatcher.java | 2 +- .../impl}/RestAuthenticationEntryPoint.java | 2 +- .../impl}/WebsocketRequestMatcher.java | 2 +- .../src/main/resources/application.yml | 5 +- .../src/main/resources/logback.xml | 2 +- 27 files changed, 305 insertions(+), 321 deletions(-) delete mode 100644 quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/DeprecatedWebSecurityConfig.java delete mode 100644 quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/LoginConfigurer.java delete mode 100644 quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/FormLoginConfig.java delete mode 100644 quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtTokenAuthenticationFilter.java create mode 100644 quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/LoginConfigurer.java rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{ => helpers/impl}/AjaxAuthenticationFilter.java (96%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/AnonAuthentication.java (87%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/AuthenticationFailureHandler.java (74%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/AuthenticationSuccessHandler.java (87%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{ => helpers/impl}/ComboEntryPoint.java (94%) create mode 100644 quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/FormLoginConfig.java rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/JwtAuthenticationFilter.java (78%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/JwtAuthenticationSuccessHandler.java (58%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/JwtAuthenticationSuccessHandlerImpl.java (69%) create mode 100644 quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenAuthenticationFilter.java rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/JwtTokenBasedAuthentication.java (88%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{ => helpers/impl}/JwtTokenHelper.java (95%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/{configuration/helpers/impl/UsernamePasswordFiterLoginConfig.java => security/helpers/impl/JwtUsernamePasswordFiterLoginConfig.java} (67%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/LogoutSuccess.java (91%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/{configuration => security}/helpers/impl/QuartzManagerHttpSecurity.java (68%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{ => helpers/impl}/RESTRequestMatcher.java (94%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{auth => helpers/impl}/RestAuthenticationEntryPoint.java (88%) rename quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/{ => helpers/impl}/WebsocketRequestMatcher.java (89%) diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/DeprecatedWebSecurityConfig.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/DeprecatedWebSecurityConfig.java deleted file mode 100644 index 5c9f8bf..0000000 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/DeprecatedWebSecurityConfig.java +++ /dev/null @@ -1,89 +0,0 @@ -package it.fabioformosa.quartzmanager.configuration; - -import javax.annotation.Resource; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.crypto.factory.PasswordEncoderFactories; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; - -import it.fabioformosa.quartzmanager.security.ComboEntryPoint; -import it.fabioformosa.quartzmanager.security.auth.AuthenticationFailureHandler; -import it.fabioformosa.quartzmanager.security.auth.AuthenticationSuccessHandler; - -@Deprecated -//@Configuration -//@EnableWebSecurity -//@EnableGlobalMethodSecurity(prePostEnabled = true) -public class DeprecatedWebSecurityConfig extends WebSecurityConfigurerAdapter { - - // @Configuration - @Order(1) - public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable() // - .antMatcher("/notifications").authorizeRequests().anyRequest().hasAnyRole("ADMIN").and() - .httpBasic(); - } - - @Override - public void configure(WebSecurity web) throws Exception { - web.ignoring().antMatchers("/","/v2/api-docs", - "/swagger-resources/**", - "/swagger-ui.html", - "/webjars/**", - "/csrf"); - } - } - - // @Configuration - @Order(2) - public static class FormWebSecurityConfig extends WebSecurityConfigurerAdapter { - - @Resource - private ComboEntryPoint comboEntryPoint; - - @Autowired - private AuthenticationSuccessHandler authenticationSuccessHandler; - - @Autowired - private AuthenticationFailureHandler authenticationFailureHandler; - - @Override - protected void configure(HttpSecurity http) throws Exception { - // http.csrf().ignoringAntMatchers("/api/login", "/api/signup").and() // - http.cors().and().csrf().disable().exceptionHandling().authenticationEntryPoint(comboEntryPoint) - .and()// - .authorizeRequests().anyRequest().authenticated().and()// - .formLogin().loginPage("/api/login").successHandler(authenticationSuccessHandler) - .failureHandler(authenticationFailureHandler).and().logout() - .logoutRequestMatcher(new AntPathRequestMatcher("/api/logout")) - .logoutSuccessUrl("/manager"); - } - - @Override - public void configure(WebSecurity web) throws Exception { - web.ignoring().antMatchers("/css/**", "/js/**", "/img/**", "/lib/**", "/webjars/**"); - } - } - - @Value("${quartz-manager.account.user}") - private String adminUser; - - @Value("${quartz-manager.account.pwd}") - private String adminPwd; - - @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); - auth.inMemoryAuthentication().withUser(adminUser).password(encoder.encode(adminPwd)).roles("ADMIN"); - } - -} diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/WebSecurityConfigJWT.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/WebSecurityConfigJWT.java index da42dea..d264134 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/WebSecurityConfigJWT.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/WebSecurityConfigJWT.java @@ -27,19 +27,19 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import com.fasterxml.jackson.databind.ObjectMapper; -import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfigurer; -import it.fabioformosa.quartzmanager.configuration.helpers.impl.FormLoginConfig; -import it.fabioformosa.quartzmanager.configuration.helpers.impl.QuartzManagerHttpSecurity; -import it.fabioformosa.quartzmanager.configuration.helpers.impl.UsernamePasswordFiterLoginConfig; import it.fabioformosa.quartzmanager.configuration.properties.InMemoryAccountProperties; import it.fabioformosa.quartzmanager.configuration.properties.JwtSecurityProperties; -import it.fabioformosa.quartzmanager.security.JwtTokenHelper; -import it.fabioformosa.quartzmanager.security.auth.AuthenticationFailureHandler; -import it.fabioformosa.quartzmanager.security.auth.AuthenticationSuccessHandler; -import it.fabioformosa.quartzmanager.security.auth.JwtAuthenticationSuccessHandler; -import it.fabioformosa.quartzmanager.security.auth.JwtAuthenticationSuccessHandlerImpl; -import it.fabioformosa.quartzmanager.security.auth.JwtTokenAuthenticationFilter; -import it.fabioformosa.quartzmanager.security.auth.LogoutSuccess; +import it.fabioformosa.quartzmanager.security.helpers.LoginConfigurer; +import it.fabioformosa.quartzmanager.security.helpers.impl.AuthenticationFailureHandler; +import it.fabioformosa.quartzmanager.security.helpers.impl.AuthenticationSuccessHandler; +import it.fabioformosa.quartzmanager.security.helpers.impl.FormLoginConfig; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtAuthenticationSuccessHandler; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtAuthenticationSuccessHandlerImpl; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtTokenAuthenticationFilter; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtTokenHelper; +import it.fabioformosa.quartzmanager.security.helpers.impl.QuartzManagerHttpSecurity; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtUsernamePasswordFiterLoginConfig; +import it.fabioformosa.quartzmanager.security.helpers.impl.LogoutSuccess; /** * @@ -76,37 +76,29 @@ public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; - // @Autowired - // private CustomUserDetailsService jwtUserDetailsService; - @Autowired private InMemoryAccountProperties inMemoryAccountProps; - // @Bean - // @Override - // public AuthenticationManager authenticationManagerBean() throws Exception { - // return super.authenticationManagerBean(); - // } @Override public void configure(AuthenticationManagerBuilder authenticationManagerBuilder)throws Exception { configureInMemoryAuthentication(authenticationManagerBuilder); - // authenticationManagerBuilder.userDetailsService(jwtUserDetailsService) - // .passwordEncoder(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { - // http.csrf().ignoringAntMatchers("/api/login", "/api/signup") // - // .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // - http.csrf().disable() // .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() // .exceptionHandling().authenticationEntryPoint(restAuthEntryPoint()).and() // .addFilterBefore(jwtAuthenticationTokenFilter(), BasicAuthenticationFilter.class) // .authorizeRequests().anyRequest().authenticated(); - QuartzManagerHttpSecurity.from(http).loginConfig(loginConfigurer(), logoutConfigurer()).login(LOGIN_PATH, authenticationManager()).logout(LOGOUT_PATH); + QuartzManagerHttpSecurity.from(http).withLoginConfigurer(loginConfigurer(), logoutConfigurer()) // + .login(LOGIN_PATH, authenticationManager()).logout(LOGOUT_PATH); + + // temporary disabled csfr + // http.csrf().ignoringAntMatchers("/api/login", "/api/signup") // + // .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // } @Override @@ -158,8 +150,7 @@ public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter { @Bean public JwtTokenHelper jwtTokenHelper() { - JwtTokenHelper jwtTokenHelper = new JwtTokenHelper(APP_NAME, jwtSecurityProps); - return jwtTokenHelper; + return new JwtTokenHelper(APP_NAME, jwtSecurityProps); } @Bean @@ -181,11 +172,6 @@ public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter { return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED); } - // @Bean - // public PasswordEncoder passwordEncoder() { - // return new BCryptPasswordEncoder(); - // } - @Bean @Override public UserDetailsService userDetailsServiceBean() throws Exception { @@ -194,8 +180,13 @@ public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter { @Bean public LoginConfigurer userpwdFilterLoginConfigurer() { - LoginConfigurer loginConfigurer = new UsernamePasswordFiterLoginConfig(jwtAuthenticationSuccessHandler()); + LoginConfigurer loginConfigurer = new JwtUsernamePasswordFiterLoginConfig(jwtAuthenticationSuccessHandler()); return loginConfigurer; } + // @Bean + // public PasswordEncoder passwordEncoder() { + // return new BCryptPasswordEncoder(); + // } + } diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/LoginConfigurer.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/LoginConfigurer.java deleted file mode 100644 index 9b9fa53..0000000 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/LoginConfigurer.java +++ /dev/null @@ -1,12 +0,0 @@ -package it.fabioformosa.quartzmanager.configuration.helpers; - -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; - -public interface LoginConfigurer { - - String cookieMustBeDeletedAtLogout(); - - HttpSecurity login(String loginPath, HttpSecurity http, AuthenticationManager authenticationManager) throws Exception; - -} diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/FormLoginConfig.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/FormLoginConfig.java deleted file mode 100644 index 72516cf..0000000 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/FormLoginConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package it.fabioformosa.quartzmanager.configuration.helpers.impl; - -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; - -import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfigurer; -import it.fabioformosa.quartzmanager.security.auth.AuthenticationFailureHandler; -import it.fabioformosa.quartzmanager.security.auth.AuthenticationSuccessHandler; - -//@Component -//@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "form-login-enabled", havingValue = "true", matchIfMissing = true) -public class FormLoginConfig implements LoginConfigurer { - - private final AuthenticationSuccessHandler authenticationSuccessHandler; - - private final AuthenticationFailureHandler authenticationFailureHandler; - - // @Autowired - public FormLoginConfig(AuthenticationSuccessHandler authenticationSuccessHandler, - AuthenticationFailureHandler authenticationFailureHandler) { - super(); - this.authenticationSuccessHandler = authenticationSuccessHandler; - this.authenticationFailureHandler = authenticationFailureHandler; - } - - @Override - public String cookieMustBeDeletedAtLogout() { - return authenticationSuccessHandler.cookieMustBeDeletedAtLogout(); - } - - @Override - public HttpSecurity login(String loginPath, - HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { - return http.formLogin().loginPage(loginPath).successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and(); - } - -} diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/controllers/AuthenticationController.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/controllers/AuthenticationController.java index 46fe68b..4b0d704 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/controllers/AuthenticationController.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/controllers/AuthenticationController.java @@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import it.fabioformosa.quartzmanager.security.JwtTokenHelper; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtTokenHelper; import it.fabioformosa.quartzmanager.security.model.UserTokenState; import it.fabioformosa.quartzmanager.security.service.impl.CustomUserDetailsService; diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtTokenAuthenticationFilter.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtTokenAuthenticationFilter.java deleted file mode 100644 index 17f8686..0000000 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtTokenAuthenticationFilter.java +++ /dev/null @@ -1,93 +0,0 @@ -package it.fabioformosa.quartzmanager.security.auth; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import org.springframework.security.web.util.matcher.OrRequestMatcher; -import org.springframework.security.web.util.matcher.RequestMatcher; -import org.springframework.util.Assert; -import org.springframework.web.filter.OncePerRequestFilter; - -import it.fabioformosa.quartzmanager.security.JwtTokenHelper; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class JwtTokenAuthenticationFilter extends OncePerRequestFilter { - - public static final String ROOT_MATCHER = "/"; - public static final String FAVICON_MATCHER = "/favicon.ico"; - public static final String HTML_MATCHER = "/**/*.html"; - public static final String CSS_MATCHER = "/**/*.css"; - public static final String JS_MATCHER = "/**/*.js"; - public static final String IMG_MATCHER = "/images/*"; - public static final String LOGIN_MATCHER = "/api/login"; - public static final String LOGOUT_MATCHER = "/api/logout"; - - // private final Log logger = LogFactory.getLog(this.getClass()); - - // @Autowired - private final JwtTokenHelper jwtTokenHelper; - - // @Autowired - private final UserDetailsService userDetailsService; - - private List pathsToSkip = Arrays.asList( - ROOT_MATCHER, - HTML_MATCHER, - FAVICON_MATCHER, - CSS_MATCHER, - JS_MATCHER, - IMG_MATCHER, - LOGIN_MATCHER, - LOGOUT_MATCHER - ); - - - public JwtTokenAuthenticationFilter(JwtTokenHelper jwtTokenHelper, UserDetailsService userDetailsService) { - super(); - this.jwtTokenHelper = jwtTokenHelper; - this.userDetailsService = userDetailsService; - } - - @Override - public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { - - String jwtToken = jwtTokenHelper.retrieveToken(request); - if (jwtToken != null && !skipPathRequest(request, pathsToSkip)) - try { - String username = jwtTokenHelper.getUsernameFromToken(jwtToken); - UserDetails userDetails = userDetailsService.loadUserByUsername(username); - // create authentication - JwtTokenBasedAuthentication authentication = new JwtTokenBasedAuthentication(userDetails); - authentication.setToken(jwtToken); - SecurityContextHolder.getContext().setAuthentication(authentication); - } catch (Exception e) { - SecurityContextHolder.getContext().setAuthentication(new AnonAuthentication()); - log.error("Switched to Anonimous Authentication, " - + "because an error occurred setting authentication in security context holder due to " + e.getMessage(), e); - } - else - SecurityContextHolder.getContext().setAuthentication(new AnonAuthentication()); - - chain.doFilter(request, response); - } - - private boolean skipPathRequest(HttpServletRequest request, List pathsToSkip ) { - Assert.notNull(pathsToSkip, "path cannot be null."); - List m = pathsToSkip.stream().map(path -> new AntPathRequestMatcher(path)).collect(Collectors.toList()); - OrRequestMatcher matchers = new OrRequestMatcher(m); - return matchers.matches(request); - } - -} \ No newline at end of file diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/LoginConfigurer.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/LoginConfigurer.java new file mode 100644 index 0000000..4446087 --- /dev/null +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/LoginConfigurer.java @@ -0,0 +1,21 @@ +package it.fabioformosa.quartzmanager.security.helpers; + +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; + +/** + * It configures filters to authenticate credentials sent by client or to set authenticationSuccessHandler + * + * Implement this interface for a login strategy + * + */ +public interface LoginConfigurer { + + /** + * If the authentication is based on cookie, it returns the name of cookie to be erased at the logout + */ + String cookieMustBeDeletedAtLogout(); + + HttpSecurity login(String loginPath, HttpSecurity http, AuthenticationManager authenticationManager) throws Exception; + +} diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/AjaxAuthenticationFilter.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AjaxAuthenticationFilter.java similarity index 96% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/AjaxAuthenticationFilter.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AjaxAuthenticationFilter.java index 1cd4bd2..0c4e0b3 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/AjaxAuthenticationFilter.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AjaxAuthenticationFilter.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.io.IOException; diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AnonAuthentication.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AnonAuthentication.java similarity index 87% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AnonAuthentication.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AnonAuthentication.java index 19796d3..f1c266f 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AnonAuthentication.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AnonAuthentication.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import org.springframework.security.authentication.AbstractAuthenticationToken; diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AuthenticationFailureHandler.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AuthenticationFailureHandler.java similarity index 74% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AuthenticationFailureHandler.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AuthenticationFailureHandler.java index 409eb45..08bb8b4 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AuthenticationFailureHandler.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AuthenticationFailureHandler.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.io.IOException; @@ -9,8 +9,6 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -//@Component -//@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "form-login-enabled", havingValue = "true", matchIfMissing = true) public class AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { @Override diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AuthenticationSuccessHandler.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AuthenticationSuccessHandler.java similarity index 87% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AuthenticationSuccessHandler.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AuthenticationSuccessHandler.java index d800130..6634870 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/AuthenticationSuccessHandler.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/AuthenticationSuccessHandler.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.io.IOException; @@ -29,7 +29,7 @@ public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccess public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication ) throws IOException, ServletException { clearAuthenticationAttributes(request); - jwtAuthenticationSuccessHandler.onSuccess(authentication, response); + jwtAuthenticationSuccessHandler.onLoginSuccess(authentication, response); } } diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/ComboEntryPoint.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/ComboEntryPoint.java similarity index 94% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/ComboEntryPoint.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/ComboEntryPoint.java index 2c05117..7ab933d 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/ComboEntryPoint.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/ComboEntryPoint.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.io.IOException; diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/FormLoginConfig.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/FormLoginConfig.java new file mode 100644 index 0000000..206f969 --- /dev/null +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/FormLoginConfig.java @@ -0,0 +1,75 @@ +package it.fabioformosa.quartzmanager.security.helpers.impl; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer; + +import it.fabioformosa.quartzmanager.security.helpers.LoginConfigurer; + +/** + * It delegates form to @FormLoginConfigurer of the httpSecurity. + * + */ +public class FormLoginConfig implements LoginConfigurer { + + private static final Logger log = LoggerFactory.getLogger(FormLoginConfig.class); + + private final AuthenticationSuccessHandler authenticationSuccessHandler; + + private final AuthenticationFailureHandler authenticationFailureHandler; + + + public FormLoginConfig() { + super(); + authenticationSuccessHandler = null; + authenticationFailureHandler = null; + } + + public FormLoginConfig(AuthenticationFailureHandler authenticationFailureHandler) { + super(); + authenticationSuccessHandler = null; + this.authenticationFailureHandler = authenticationFailureHandler; + } + + public FormLoginConfig(AuthenticationSuccessHandler authenticationSuccessHandler) { + super(); + this.authenticationSuccessHandler = authenticationSuccessHandler; + authenticationFailureHandler = null; + } + + public FormLoginConfig(AuthenticationSuccessHandler authenticationSuccessHandler, + AuthenticationFailureHandler authenticationFailureHandler) { + super(); + this.authenticationSuccessHandler = authenticationSuccessHandler; + this.authenticationFailureHandler = authenticationFailureHandler; + } + + @Override + public String cookieMustBeDeletedAtLogout() { + return authenticationSuccessHandler.cookieMustBeDeletedAtLogout(); + } + + @Override + public HttpSecurity login(String loginPath, + HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { + log.debug("Configuring login through FormLoginConfigurer..."); + + FormLoginConfigurer login = http.formLogin().loginPage(loginPath); + + if(authenticationSuccessHandler != null) { + log.debug("Setting an authenticationSuccessHandler"); + login = login.successHandler(authenticationSuccessHandler); + } + + if(authenticationFailureHandler != null) { + log.debug("Setting an authenticationFailureHandler"); + login = login.failureHandler(authenticationFailureHandler); + } + + HttpSecurity httpSecurity = login.and(); + return httpSecurity; + } + +} diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationFilter.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationFilter.java similarity index 78% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationFilter.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationFilter.java index 7d43fa8..c15c0ac 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationFilter.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationFilter.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import javax.servlet.FilterChain; import javax.servlet.http.HttpServletRequest; @@ -10,6 +10,10 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic import lombok.SneakyThrows; +/** + * It extends the @UsernamePasswordAuthenticationFilter and it overrides the successfulAuthentication method to put jwtToken in the response + * + */ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler; @@ -25,6 +29,6 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte HttpServletResponse res, FilterChain chain, Authentication auth) { - jwtAuthenticationSuccessHandler.onSuccess(auth, res); + jwtAuthenticationSuccessHandler.onLoginSuccess(auth, res); } } diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationSuccessHandler.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandler.java similarity index 58% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationSuccessHandler.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandler.java index 91356d7..6a956c9 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationSuccessHandler.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandler.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.io.IOException; @@ -7,7 +7,8 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; public interface JwtAuthenticationSuccessHandler { - void onSuccess(Authentication authentication, HttpServletResponse response) throws IOException; String cookieMustBeDeletedAtLogout(); + + void onLoginSuccess(Authentication authentication, HttpServletResponse response) throws IOException; } diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationSuccessHandlerImpl.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandlerImpl.java similarity index 69% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationSuccessHandlerImpl.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandlerImpl.java index cffe01d..fee0ede 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationSuccessHandlerImpl.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandlerImpl.java @@ -1,10 +1,12 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.io.IOException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.User; @@ -12,20 +14,24 @@ import org.springframework.security.core.userdetails.User; import com.fasterxml.jackson.databind.ObjectMapper; import it.fabioformosa.quartzmanager.configuration.properties.JwtSecurityProperties; -import it.fabioformosa.quartzmanager.security.JwtTokenHelper; import it.fabioformosa.quartzmanager.security.model.UserTokenState; -//@Component +/** + * It depends on @JwtTokenHelper to generate the jwtToken. + * On login success, it generates the jwtToken and it returns it to the login according to possible strategies: cookie, response header. + * You can choice the strategy through @JwtSecurityProperties + * + */ public class JwtAuthenticationSuccessHandlerImpl implements JwtAuthenticationSuccessHandler { - // @Autowired + private static final Logger log = LoggerFactory.getLogger(JwtAuthenticationSuccessHandlerImpl.class); + private final JwtSecurityProperties jwtSecurityProps; private final JwtTokenHelper jwtTokenHelper; private final ObjectMapper objectMapper; - // @Value("${server.servlet.context-path}") private final String contextPath; @Autowired @@ -44,9 +50,10 @@ public class JwtAuthenticationSuccessHandlerImpl implements JwtAuthenticationSuc } @Override - public void onSuccess(Authentication authentication, HttpServletResponse response) throws IOException { - User user = (User) authentication.getPrincipal(); + public void onLoginSuccess(Authentication authentication, HttpServletResponse response) throws IOException { + log.debug("Login successed, generating jwtToken..."); + User user = (User) authentication.getPrincipal(); String jwtToken = jwtTokenHelper.generateToken(user.getUsername()); if(jwtSecurityProps.getCookieStrategy().isEnabled()) { @@ -55,10 +62,13 @@ public class JwtAuthenticationSuccessHandlerImpl implements JwtAuthenticationSuc authCookie.setMaxAge((int) jwtSecurityProps.getExpirationInSec()); authCookie.setPath(contextPath); response.addCookie(authCookie); + log.debug("Set jwtToken into the cookie {}", jwtSecurityProps.getCookieStrategy().getCookie()); } - if(jwtSecurityProps.getHeaderStrategy().isEnabled()) + if(jwtSecurityProps.getHeaderStrategy().isEnabled()) { jwtTokenHelper.setHeader(response, jwtToken); + log.debug("Set jwtToken into the response header {}", jwtSecurityProps.getHeaderStrategy().getHeader()); + } UserTokenState userTokenState = new UserTokenState(jwtToken, jwtSecurityProps.getExpirationInSec()); String jwtResponse = objectMapper.writeValueAsString(userTokenState); diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenAuthenticationFilter.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenAuthenticationFilter.java new file mode 100644 index 0000000..346bb2f --- /dev/null +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenAuthenticationFilter.java @@ -0,0 +1,105 @@ +package it.fabioformosa.quartzmanager.security.helpers.impl; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.OrRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.web.filter.OncePerRequestFilter; + + +/** + * It finds the jwtToken into the request, it validates it and sets an @Authentication into the @SecurityContextHolder. + * If the request has a path included into the paths that must be skipped, it sets an anonymous authentication + * + * It delegates the jwtToken retrieve to the @JwtTokenHelper that applies several strategies. + * + */ +public class JwtTokenAuthenticationFilter extends OncePerRequestFilter { + + private static final Logger log = LoggerFactory.getLogger(JwtTokenAuthenticationFilter.class); + + private static final String ROOT_MATCHER = "/"; + private static final String FAVICON_MATCHER = "/favicon.ico"; + private static final String HTML_MATCHER = "/**/*.html"; + private static final String CSS_MATCHER = "/**/*.css"; + private static final String JS_MATCHER = "/**/*.js"; + private static final String IMG_MATCHER = "/images/*"; + private static final String LOGIN_MATCHER = "/api/login"; + private static final String LOGOUT_MATCHER = "/api/logout"; + + private static List PATH_TO_SKIP = Arrays.asList( + ROOT_MATCHER, + HTML_MATCHER, + FAVICON_MATCHER, + CSS_MATCHER, + JS_MATCHER, + IMG_MATCHER, + LOGIN_MATCHER, + LOGOUT_MATCHER + ); + + private final JwtTokenHelper jwtTokenHelper; + private final UserDetailsService userDetailsService; + + + public JwtTokenAuthenticationFilter(JwtTokenHelper jwtTokenHelper, UserDetailsService userDetailsService) { + super(); + this.jwtTokenHelper = jwtTokenHelper; + this.userDetailsService = userDetailsService; + } + + @Override + public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + + String jwtToken = jwtTokenHelper.retrieveToken(request); + if (jwtToken != null) { + log.debug("Found a jwtToken into the request {}", request.getPathInfo()); + try { + String username = jwtTokenHelper.getUsernameFromToken(jwtToken); + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + + JwtTokenBasedAuthentication authentication = new JwtTokenBasedAuthentication(userDetails); + authentication.setToken(jwtToken); + + SecurityContextHolder.getContext().setAuthentication(authentication); + } catch (Exception e) { + log.error("Authentication failed! an expected error occurred authenticating the request {}", request.getRequestURL()); + // SecurityContextHolder.getContext().setAuthentication(new AnonAuthentication()); + // log.error("Switched to Anonymous Authentication, " + // + "because an error occurred setting authentication in security context holder due to " + e.getMessage(), e); + } + } + else if(skipPathRequest(request, PATH_TO_SKIP)) { + log.debug("Detected a path to be skipped from authentication, so activated anonymous auth for {}", request.getRequestURL()); + SecurityContextHolder.getContext().setAuthentication(new AnonAuthentication()); + } + else + log.debug("Not found any jwtToken and the request hasn't a path to be skipped from auth. Path: {}", request.getRequestURL()); + + chain.doFilter(request, response); + } + + private boolean skipPathRequest(HttpServletRequest request, List pathsToSkip ) { + if(pathsToSkip == null) + pathsToSkip = new ArrayList(); + List matchers = pathsToSkip.stream().map(path -> new AntPathRequestMatcher(path)).collect(Collectors.toList()); + OrRequestMatcher compositeMatchers = new OrRequestMatcher(matchers); + return compositeMatchers.matches(request); + } + +} \ No newline at end of file diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtTokenBasedAuthentication.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenBasedAuthentication.java similarity index 88% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtTokenBasedAuthentication.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenBasedAuthentication.java index 2938674..904ed07 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtTokenBasedAuthentication.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenBasedAuthentication.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.userdetails.UserDetails; diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/JwtTokenHelper.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenHelper.java similarity index 95% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/JwtTokenHelper.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenHelper.java index df08bed..cc51e3d 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/JwtTokenHelper.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenHelper.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -10,12 +10,13 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import it.fabioformosa.quartzmanager.configuration.properties.JwtSecurityProperties; -import lombok.extern.slf4j.Slf4j; /** * @@ -23,16 +24,17 @@ import lombok.extern.slf4j.Slf4j; * */ -@Slf4j -//@Component public class JwtTokenHelper { + private static final Logger log = LoggerFactory.getLogger(JwtTokenHelper.class); + private static String base64EncodeSecretKey(String secretKey) { return Base64.getEncoder().encodeToString(secretKey.getBytes(StandardCharsets.UTF_8)); } // @Value("${app.name}") private final String appName; + // @Autowired private final JwtSecurityProperties jwtSecurityProps; @@ -117,6 +119,7 @@ public class JwtTokenHelper { } catch (Exception e) { username = null; log.error("Error getting claims from jwt token due to " + e.getMessage(), e); + throw e; } return username; } diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/UsernamePasswordFiterLoginConfig.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtUsernamePasswordFiterLoginConfig.java similarity index 67% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/UsernamePasswordFiterLoginConfig.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtUsernamePasswordFiterLoginConfig.java index f938822..6f6991c 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/UsernamePasswordFiterLoginConfig.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtUsernamePasswordFiterLoginConfig.java @@ -1,5 +1,7 @@ -package it.fabioformosa.quartzmanager.configuration.helpers.impl; +package it.fabioformosa.quartzmanager.security.helpers.impl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -7,18 +9,19 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen import org.springframework.security.web.util.matcher.RegexRequestMatcher; import org.springframework.web.filter.GenericFilterBean; -import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfigurer; -import it.fabioformosa.quartzmanager.security.auth.JwtAuthenticationFilter; -import it.fabioformosa.quartzmanager.security.auth.JwtAuthenticationSuccessHandler; +import it.fabioformosa.quartzmanager.security.helpers.LoginConfigurer; -//@Component -//@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "userpwd-filter-enabled", havingValue = "true", matchIfMissing = false) -public class UsernamePasswordFiterLoginConfig implements LoginConfigurer { +/** + * It adds a new filter @JwtAuthenticationFilter after @AbstractPreAuthenticatedProcessingFilter that match login path + * + */ +public class JwtUsernamePasswordFiterLoginConfig implements LoginConfigurer { + + private static final Logger log = LoggerFactory.getLogger(JwtUsernamePasswordFiterLoginConfig.class); - // @Autowired private final JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler; - public UsernamePasswordFiterLoginConfig(JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler) { + public JwtUsernamePasswordFiterLoginConfig(JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler) { super(); this.jwtAuthenticationSuccessHandler = jwtAuthenticationSuccessHandler; } @@ -36,6 +39,7 @@ public class UsernamePasswordFiterLoginConfig implements LoginConfigurer { @Override public HttpSecurity login(String loginPath, HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { + log.debug("Configuring login through JwtAuthenticationFilter..."); return http.addFilterAfter(authenticationProcessingFilter(loginPath, authenticationManager), AbstractPreAuthenticatedProcessingFilter.class); } diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/LogoutSuccess.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/LogoutSuccess.java similarity index 91% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/LogoutSuccess.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/LogoutSuccess.java index f185289..5f0eaa0 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/LogoutSuccess.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/LogoutSuccess.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.io.IOException; import java.util.HashMap; @@ -17,7 +17,6 @@ public class LogoutSuccess implements LogoutSuccessHandler { private final ObjectMapper objectMapper; - // @Autowired public LogoutSuccess(ObjectMapper objectMapper) { super(); this.objectMapper = objectMapper; diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/QuartzManagerHttpSecurity.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/QuartzManagerHttpSecurity.java similarity index 68% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/QuartzManagerHttpSecurity.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/QuartzManagerHttpSecurity.java index e52c7ad..55b9edb 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/QuartzManagerHttpSecurity.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/QuartzManagerHttpSecurity.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.configuration.helpers.impl; +package it.fabioformosa.quartzmanager.security.helpers.impl; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; @@ -7,9 +7,12 @@ import org.springframework.security.config.annotation.web.configurers.LogoutConf import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfigurer; -import it.fabioformosa.quartzmanager.security.auth.LogoutSuccess; +import it.fabioformosa.quartzmanager.security.helpers.LoginConfigurer; +/** + * It wraps the httpSecurity to provide new function as login and logout + * + */ public class QuartzManagerHttpSecurity extends SecurityConfigurerAdapter { public static QuartzManagerHttpSecurity from(HttpSecurity httpSecurity){ @@ -20,35 +23,35 @@ public class QuartzManagerHttpSecurity extends SecurityConfigurerAdapter logout(String logoutPath) throws Exception { LogoutConfigurer logoutConfigurer = httpSecurity.logout().logoutRequestMatcher(new AntPathRequestMatcher(logoutPath)) .logoutSuccessHandler(logoutSuccess); - String cookie = loginConfiger.cookieMustBeDeletedAtLogout(); + String cookie = loginConfigurer.cookieMustBeDeletedAtLogout(); if(cookie != null) logoutConfigurer.deleteCookies(cookie); return logoutConfigurer; } + + public QuartzManagerHttpSecurity withLoginConfigurer(LoginConfigurer loginConfigurer, LogoutSuccess logoutSuccess) { + this.loginConfigurer = loginConfigurer; + this.logoutSuccess = logoutSuccess; + return this; + } } diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/RESTRequestMatcher.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/RESTRequestMatcher.java similarity index 94% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/RESTRequestMatcher.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/RESTRequestMatcher.java index 899d5ad..1fb2d2b 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/RESTRequestMatcher.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/RESTRequestMatcher.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security; +package it.fabioformosa.quartzmanager.security.helpers.impl; import javax.servlet.http.HttpServletRequest; diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/RestAuthenticationEntryPoint.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/RestAuthenticationEntryPoint.java similarity index 88% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/RestAuthenticationEntryPoint.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/RestAuthenticationEntryPoint.java index 1d1c4be..3615a2e 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/RestAuthenticationEntryPoint.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/RestAuthenticationEntryPoint.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.auth; +package it.fabioformosa.quartzmanager.security.helpers.impl; import java.io.IOException; diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/WebsocketRequestMatcher.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/WebsocketRequestMatcher.java similarity index 89% rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/WebsocketRequestMatcher.java rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/WebsocketRequestMatcher.java index 28f64db..5b42424 100644 --- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/WebsocketRequestMatcher.java +++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/WebsocketRequestMatcher.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security; +package it.fabioformosa.quartzmanager.security.helpers.impl; import javax.servlet.http.HttpServletRequest; diff --git a/quartz-manager-api/src/main/resources/application.yml b/quartz-manager-api/src/main/resources/application.yml index ae82d02..f69a691 100644 --- a/quartz-manager-api/src/main/resources/application.yml +++ b/quartz-manager-api/src/main/resources/application.yml @@ -11,6 +11,7 @@ spring: thymeleaf: cache: false mode: LEGACYHTML5 + jpa.open-in-view: false quartz: enabled: true @@ -36,10 +37,10 @@ quartz-manager: secret: "bibidibobidiboo" expiration-in-sec: 28800 # 8 hours header-strategy: - enabled: true + enabled: false header: "Authorization" cookie-strategy: - enabled: false + enabled: true cookie: AUTH-TOKEN jobClass: it.fabioformosa.quartzmanager.jobs.myjobs.SampleJob accounts: diff --git a/quartz-manager-api/src/main/resources/logback.xml b/quartz-manager-api/src/main/resources/logback.xml index 9977078..90577b1 100644 --- a/quartz-manager-api/src/main/resources/logback.xml +++ b/quartz-manager-api/src/main/resources/logback.xml @@ -4,7 +4,7 @@ - %d{yyyy-MM-dd HH:mm:ss.SSS} [%.10thread] %-5level [%-40.40logger{49}:%-3L] --- %m%n + %d{yyyy-MM-dd HH:mm:ss.SSS} [%.11thread] %-5level [%-40.40logger{49}:%-3L] --- %m%n