diff --git a/quartz-manager-api/pom.xml b/quartz-manager-api/pom.xml
index 72afb43..dbce52a 100644
--- a/quartz-manager-api/pom.xml
+++ b/quartz-manager-api/pom.xml
@@ -164,7 +164,12 @@
provided
-
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
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 77bb44f..16bedb9 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
@@ -4,7 +4,10 @@ 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.http.HttpMethod;
+import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
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;
@@ -14,16 +17,17 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
-import it.fabioformosa.quartzmanager.security.auth.AuthenticationFailureHandler;
-import it.fabioformosa.quartzmanager.security.auth.AuthenticationSuccessHandler;
+import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfig;
+import it.fabioformosa.quartzmanager.configuration.properties.InMemoryAccountProperties;
import it.fabioformosa.quartzmanager.security.auth.LogoutSuccess;
-import it.fabioformosa.quartzmanager.security.auth.RestAuthenticationEntryPoint;
import it.fabioformosa.quartzmanager.security.auth.TokenAuthenticationFilter;
/**
@@ -37,91 +41,96 @@ import it.fabioformosa.quartzmanager.security.auth.TokenAuthenticationFilter;
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter {
- @Value("${jwt.cookie}")
- private String TOKEN_COOKIE;
+ private static final String[] PATTERNS_SWAGGER_UI = {"/swagger-ui.html", "/v2/api-docs", "/swagger-resources/**", "/webjars/**"};
- // @Autowired
- // private CustomUserDetailsService jwtUserDetailsService;
+ @Value("${quartz-manager.security.jwt.cookie}")
+ private String TOKEN_COOKIE;
- @Autowired
- private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
+ // @Autowired
+ // private CustomUserDetailsService jwtUserDetailsService;
- @Autowired
- private LogoutSuccess logoutSuccess;
+ @Autowired
+ private LogoutSuccess logoutSuccess;
- @Autowired
- private AuthenticationSuccessHandler authenticationSuccessHandler;
+ @Autowired
+ private LoginConfig loginConfigurer;
- @Autowired
- private AuthenticationFailureHandler authenticationFailureHandler;
+ @Autowired
+ private InMemoryAccountProperties inMemoryAccountProps;
- @Value("${quartz-manager.account.user}")
- private String adminUser;
+ // @Bean
+ // @Override
+ // public AuthenticationManager authenticationManagerBean() throws Exception {
+ // return super.authenticationManagerBean();
+ // }
- @Value("${quartz-manager.account.pwd}")
- private String adminPwd;
+ @Override
+ public void configure(AuthenticationManagerBuilder authenticationManagerBuilder)throws Exception {
+ configureInMemoryAuthentication(authenticationManagerBuilder);
+ // authenticationManagerBuilder.userDetailsService(jwtUserDetailsService)
+ // .passwordEncoder(passwordEncoder());
+ }
- // @Bean
- // @Override
- // public AuthenticationManager authenticationManagerBean() throws Exception {
- // return super.authenticationManagerBean();
- // }
+ @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();
- @Override
- public void configure(WebSecurity web) throws Exception {
- web.ignoring().antMatchers("/css/**", //
- "/js/**", //
- "/img/**", //
- "/lib/**", //
- "/swagger-resources/**", "/swagger-ui.html","/v2/api-docs", //
- "/webjars/**");
- }
+ loginConfigurer.configureLoginHandler(http, authenticationManager()).logout().logoutRequestMatcher(new AntPathRequestMatcher("/api/logout"))
+ .logoutSuccessHandler(logoutSuccess).deleteCookies(TOKEN_COOKIE);
- @Autowired
- public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder)
- throws Exception {
- // authenticationManagerBuilder.userDetailsService(jwtUserDetailsService)
- // .passwordEncoder(passwordEncoder());
- PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
- authenticationManagerBuilder.inMemoryAuthentication().withUser(adminUser).password(encoder.encode(adminPwd)).roles("ADMIN");
- }
+ }
- @Bean
- public TokenAuthenticationFilter jwtAuthenticationTokenFilter() throws Exception {
- return new TokenAuthenticationFilter();
- }
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring()//
+ .antMatchers(HttpMethod.GET, PATTERNS_SWAGGER_UI) //
+ .antMatchers(HttpMethod.GET,"/css/**", "/js/**", "/img/**", "/lib/**");
+ }
- @Bean
- @Override
- public UserDetailsService userDetailsServiceBean() throws Exception {
- return super.userDetailsServiceBean();
- }
+ private void configureInMemoryAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
+ PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
+ if(inMemoryAccountProps.isEnabled() && inMemoryAccountProps.getUsers() != null && !inMemoryAccountProps.getUsers().isEmpty()) {
+ InMemoryUserDetailsManagerConfigurer inMemoryAuth = authenticationManagerBuilder.inMemoryAuthentication();
+ inMemoryAccountProps.getUsers()
+ .forEach(u -> inMemoryAuth
+ .withUser(u.getName())
+ .password(encoder.encode(u.getPassword()))
+ .roles(u.getRoles().toArray(new String[0])));
+ }
+ }
- // @Bean
- // public PasswordEncoder passwordEncoder() {
- // return new BCryptPasswordEncoder();
- // }
+ @Bean
+ CorsConfigurationSource corsConfigurationSource() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
+ return source;
+ }
- @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(restAuthenticationEntryPoint).and()
- .addFilterBefore(jwtAuthenticationTokenFilter(), BasicAuthenticationFilter.class)
- .authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/api/login")
- .successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler)
- .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/api/logout"))
- .logoutSuccessHandler(logoutSuccess).deleteCookies(TOKEN_COOKIE);
+ @Bean
+ public TokenAuthenticationFilter jwtAuthenticationTokenFilter() throws Exception {
+ return new TokenAuthenticationFilter();
+ }
- }
+ // @Bean
+ // public PasswordEncoder passwordEncoder() {
+ // return new BCryptPasswordEncoder();
+ // }
- @Bean
- CorsConfigurationSource corsConfigurationSource() {
- UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
- return source;
- }
+ @Bean
+ public AuthenticationEntryPoint restAuthEntryPoint() {
+ return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED);
+ }
+
+ @Bean
+ @Override
+ public UserDetailsService userDetailsServiceBean() throws Exception {
+ return super.userDetailsServiceBean();
+ }
}
diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/LoginConfig.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/LoginConfig.java
new file mode 100644
index 0000000..be5b2fd
--- /dev/null
+++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/LoginConfig.java
@@ -0,0 +1,10 @@
+package it.fabioformosa.quartzmanager.configuration.helpers;
+
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+
+public interface LoginConfig {
+
+ HttpSecurity configureLoginHandler(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
new file mode 100644
index 0000000..e683754
--- /dev/null
+++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/FormLoginConfig.java
@@ -0,0 +1,31 @@
+package it.fabioformosa.quartzmanager.configuration.helpers.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.stereotype.Component;
+
+import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfig;
+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 LoginConfig {
+
+ private static final String API_LOGIN = "/api/login";
+
+ @Autowired
+ private AuthenticationSuccessHandler authenticationSuccessHandler;
+
+ @Autowired
+ private AuthenticationFailureHandler authenticationFailureHandler;
+
+ @Override
+ public HttpSecurity configureLoginHandler(
+ HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
+ return http.formLogin().loginPage(API_LOGIN).successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and();
+ }
+
+}
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/configuration/helpers/impl/UsernamePasswordFiterLoginConfig.java
new file mode 100644
index 0000000..4d26310
--- /dev/null
+++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/helpers/impl/UsernamePasswordFiterLoginConfig.java
@@ -0,0 +1,37 @@
+package it.fabioformosa.quartzmanager.configuration.helpers.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
+import org.springframework.security.web.util.matcher.RegexRequestMatcher;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.GenericFilterBean;
+
+import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfig;
+import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
+import it.fabioformosa.quartzmanager.security.auth.JwtAuthenticationFilter;
+
+@Component
+@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "userpwd-filter-enabled", havingValue = "true", matchIfMissing = false)
+public class UsernamePasswordFiterLoginConfig implements LoginConfig {
+
+ private static final String API_LOGIN = "/api/login";
+
+ @Autowired
+ private JwtTokenHelper jwtTokenHelper;
+
+ public GenericFilterBean authenticationProcessingFilter(AuthenticationManager authenticationManager) throws Exception {
+ JwtAuthenticationFilter authenticationProcessingFilter = new JwtAuthenticationFilter(authenticationManager, jwtTokenHelper);
+ authenticationProcessingFilter.setRequiresAuthenticationRequestMatcher(new RegexRequestMatcher(API_LOGIN, HttpMethod.POST.name(), false));
+ return authenticationProcessingFilter;
+ }
+
+ @Override
+ public HttpSecurity configureLoginHandler(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
+ return http.addFilterAfter(authenticationProcessingFilter(authenticationManager), AbstractPreAuthenticatedProcessingFilter.class);
+ }
+
+}
diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/properties/InMemoryAccountProperties.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/properties/InMemoryAccountProperties.java
new file mode 100644
index 0000000..a6905ba
--- /dev/null
+++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/properties/InMemoryAccountProperties.java
@@ -0,0 +1,24 @@
+package it.fabioformosa.quartzmanager.configuration.properties;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Configuration
+@ConfigurationProperties(prefix = "quartz-manager.accounts.in-memory")
+@Getter @Setter
+public class InMemoryAccountProperties {
+ private boolean enabled;
+ private List users;
+
+ @Getter @Setter
+ public static class User {
+ private String name;
+ private String password;
+ private List roles = new ArrayList<>();
+ }
+}
diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/properties/JwtSecurityProperties.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/properties/JwtSecurityProperties.java
new file mode 100644
index 0000000..d2e9f49
--- /dev/null
+++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/configuration/properties/JwtSecurityProperties.java
@@ -0,0 +1,17 @@
+package it.fabioformosa.quartzmanager.configuration.properties;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix = "quartz-manager.security.jwt")
+@Getter @Setter
+public class JwtSecurityProperties {
+ private boolean enabled;
+ private String secret;
+ private long expirationInSec;
+ private String header;
+ private String cookie;
+}
\ No newline at end of file
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 61f64a4..74f25d8 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.TokenHelper;
+import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
import it.fabioformosa.quartzmanager.security.model.UserTokenState;
import it.fabioformosa.quartzmanager.security.service.impl.CustomUserDetailsService;
@@ -39,12 +39,12 @@ public class AuthenticationController {
private CustomUserDetailsService userDetailsService;
@Autowired
- TokenHelper tokenHelper;
+ JwtTokenHelper tokenHelper;
- @Value("${jwt.expires_in_sec}")
+ @Value("${quartz-manager.security.jwt.expiration-in-sec}")
private int EXPIRES_IN_SEC;
- @Value("${jwt.cookie}")
+ @Value("${quartz-manager.security.jwt.cookie}")
private String TOKEN_COOKIE;
@RequestMapping(value = "/changePassword", method = RequestMethod.POST)
diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/TokenHelper.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/JwtTokenHelper.java
similarity index 69%
rename from quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/TokenHelper.java
rename to quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/JwtTokenHelper.java
index 6576838..e3b2b82 100644
--- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/TokenHelper.java
+++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/JwtTokenHelper.java
@@ -1,22 +1,26 @@
package it.fabioformosa.quartzmanager.security;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.joda.time.DateTime;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
+import it.fabioformosa.quartzmanager.configuration.properties.JwtSecurityProperties;
import lombok.extern.slf4j.Slf4j;
/**
- * JWT Temporary disabled
*
* @author Fabio.Formosa
*
@@ -24,25 +28,32 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
-public class TokenHelper {
+public class JwtTokenHelper {
+
+ private static String base64EncodeSecretKey(String secretKey) {
+ return Base64.getEncoder().encodeToString(secretKey.getBytes(StandardCharsets.UTF_8));
+ }
@Value("${app.name}")
private String APP_NAME;
- @Value("${jwt.secret}")
- private String SECRET;
-
- @Value("${jwt.expires_in_sec}")
- private int EXPIRES_IN_SEC;
-
- @Value("${jwt.header}")
- private String AUTH_HEADER;
-
- @Value("${jwt.cookie}")
- private String AUTH_COOKIE;
+ // @Value("${jwt.secret}")
+ // private String SECRET;
+ //
+ // @Value("${jwt.expires_in_sec}")
+ // private int EXPIRES_IN_SEC;
+ //
+ // @Value("${jwt.header}")
+ // private String AUTH_HEADER;
// @Autowired
// UserDetailsService userDetailsService;
+ //
+ // @Value("${jwt.cookie}")
+ // private String AUTH_COOKIE;
+
+ @Autowired
+ private JwtSecurityProperties jwtSecurityProps;
private SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS512;
@@ -62,14 +73,14 @@ public class TokenHelper {
}
private Date generateExpirationDate() {
- return new Date(getCurrentTimeMillis() + EXPIRES_IN_SEC * 1000);
+ return new Date(getCurrentTimeMillis() + jwtSecurityProps.getExpirationInSec() * 1000);
}
- String generateToken(Map claims) {
+ private String generateToken(Map claims) {
return Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
- .signWith( SIGNATURE_ALGORITHM, SECRET )
+ .signWith( SIGNATURE_ALGORITHM, base64EncodeSecretKey(jwtSecurityProps.getSecret()))
.compact();
}
@@ -79,7 +90,7 @@ public class TokenHelper {
.setSubject(username)
.setIssuedAt(generateCurrentDate())
.setExpiration(generateExpirationDate())
- .signWith(SIGNATURE_ALGORITHM, SECRET)
+ .signWith(SIGNATURE_ALGORITHM, base64EncodeSecretKey(jwtSecurityProps.getSecret()))
.compact();
}
@@ -87,7 +98,7 @@ public class TokenHelper {
Claims claims;
try {
claims = Jwts.parser()
- .setSigningKey(SECRET)
+ .setSigningKey(base64EncodeSecretKey(jwtSecurityProps.getSecret()))
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
@@ -119,12 +130,12 @@ public class TokenHelper {
return DateTime.now().getMillis();
}
- public String getToken( HttpServletRequest request ) {
- Cookie authCookie = getCookieValueByName( request, AUTH_COOKIE );
+ public String getToken(HttpServletRequest request) {
+ Cookie authCookie = getCookieValueByName(request, jwtSecurityProps.getCookie());
if ( authCookie != null )
return authCookie.getValue();
- String authHeader = request.getHeader(AUTH_HEADER);
+ String authHeader = request.getHeader(jwtSecurityProps.getHeader());
if ( authHeader != null && authHeader.startsWith("Bearer "))
return authHeader.substring(7);
@@ -155,4 +166,8 @@ public class TokenHelper {
}
return refreshedToken;
}
+
+ public void setHeader(HttpServletResponse response, String token) {
+ response.addHeader(jwtSecurityProps.getHeader(), "Bearer " + token);
+ }
}
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/auth/AuthenticationFailureHandler.java
index a57f6e1..e170b96 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/auth/AuthenticationFailureHandler.java
@@ -6,17 +6,19 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
@Component
+@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "form-login-enabled", havingValue = "true", matchIfMissing = true)
public class AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
- @Override
- public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
- AuthenticationException exception) throws IOException, ServletException {
+ @Override
+ public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException exception) throws IOException, ServletException {
- super.onAuthenticationFailure(request, response, exception);
- }
+ super.onAuthenticationFailure(request, response, exception);
+ }
}
\ No newline at end of file
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/auth/AuthenticationSuccessHandler.java
index 9f3bd77..df6d282 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/auth/AuthenticationSuccessHandler.java
@@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
@@ -16,54 +17,52 @@ import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
-import it.fabioformosa.quartzmanager.security.TokenHelper;
+import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
import it.fabioformosa.quartzmanager.security.model.UserTokenState;
@Component
+@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "form-login-enabled", havingValue = "true", matchIfMissing = true)
public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
- @Value("${jwt.expires_in_sec}")
- private int EXPIRES_IN_SEC;
+ @Value("${quartz-manager.security.jwt.expiration-in-sec}")
+ private int EXPIRES_IN_SEC;
- @Value("${jwt.cookie}")
- private String TOKEN_COOKIE;
+ @Value("${quartz-manager.security.jwt.cookie}")
+ private String TOKEN_COOKIE;
- @Autowired
- TokenHelper tokenHelper;
- //
- @Autowired
- ObjectMapper objectMapper;
+ @Autowired
+ JwtTokenHelper tokenHelper;
+ //
+ @Autowired
+ ObjectMapper objectMapper;
- @Override
- public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
- Authentication authentication ) throws IOException, ServletException {
- clearAuthenticationAttributes(request);
- User user = (User)authentication.getPrincipal();
+ @Override
+ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
+ Authentication authentication ) throws IOException, ServletException {
+ clearAuthenticationAttributes(request);
+ User user = (User) authentication.getPrincipal();
- String jws = tokenHelper.generateToken( user.getUsername() );
+ String jws = tokenHelper.generateToken(user.getUsername());
- Cookie authCookie = new Cookie( TOKEN_COOKIE, jws );
+ Cookie authCookie = new Cookie( TOKEN_COOKIE, jws );
+ authCookie.setHttpOnly(true);
+ authCookie.setMaxAge(EXPIRES_IN_SEC);
+ authCookie.setPath( "/quartz-manager" );
+ response.addCookie(authCookie);
- authCookie.setHttpOnly( true );
+ // JWT is also in the response
+ UserTokenState userTokenState = new UserTokenState(jws, EXPIRES_IN_SEC);
+ String jwtResponse = objectMapper.writeValueAsString( userTokenState );
+ response.setContentType("application/json");
+ response.getWriter().write( jwtResponse );
- authCookie.setMaxAge( EXPIRES_IN_SEC );
+ }
- authCookie.setPath( "/quartz-manager" );
- response.addCookie( authCookie );
-
- // JWT is also in the response
- UserTokenState userTokenState = new UserTokenState(jws, EXPIRES_IN_SEC);
- String jwtResponse = objectMapper.writeValueAsString( userTokenState );
- response.setContentType("application/json");
- response.getWriter().write( jwtResponse );
-
- }
-
- // @Override
- // public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
- // Authentication authentication ) throws IOException, ServletException {
- // // clearAuthenticationAttributes(request);
- // response.setContentType("application/json");
- // response.getWriter().write( objectMapper.writeValueAsString("OK"));
- // }
+ // @Override
+ // public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
+ // Authentication authentication ) throws IOException, ServletException {
+ // // clearAuthenticationAttributes(request);
+ // response.setContentType("application/json");
+ // response.getWriter().write( objectMapper.writeValueAsString("OK"));
+ // }
}
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/auth/JwtAuthenticationFilter.java
new file mode 100644
index 0000000..a8ec266
--- /dev/null
+++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/JwtAuthenticationFilter.java
@@ -0,0 +1,32 @@
+package it.fabioformosa.quartzmanager.security.auth;
+
+import javax.servlet.FilterChain;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
+
+public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
+
+ private final JwtTokenHelper jwtTokenHelper;
+
+ public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtTokenHelper jwtTokenHelper) {
+ this.jwtTokenHelper = jwtTokenHelper;
+ setAuthenticationManager(authenticationManager);
+ }
+
+ @Override
+ protected void successfulAuthentication(HttpServletRequest req,
+ HttpServletResponse res,
+ FilterChain chain,
+ Authentication auth) {
+ UserDetails user = (UserDetails) auth.getPrincipal();
+ String token = jwtTokenHelper.generateToken(user.getUsername());
+ jwtTokenHelper.setHeader(res, token);
+ }
+}
\ No newline at end of file
diff --git a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/TokenAuthenticationFilter.java b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/TokenAuthenticationFilter.java
index b0856ad..70a1aaf 100644
--- a/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/TokenAuthenticationFilter.java
+++ b/quartz-manager-api/src/main/java/it/fabioformosa/quartzmanager/security/auth/TokenAuthenticationFilter.java
@@ -20,7 +20,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
-import it.fabioformosa.quartzmanager.security.TokenHelper;
+import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@@ -38,7 +38,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
// private final Log logger = LogFactory.getLog(this.getClass());
@Autowired
- private TokenHelper tokenHelper;
+ private JwtTokenHelper tokenHelper;
@Autowired
private UserDetailsService userDetailsService;
diff --git a/quartz-manager-api/src/main/resources/application.yml b/quartz-manager-api/src/main/resources/application.yml
index c4c71ce..bfa8435 100644
--- a/quartz-manager-api/src/main/resources/application.yml
+++ b/quartz-manager-api/src/main/resources/application.yml
@@ -19,12 +19,6 @@ job:
frequency: 4000
repeatCount: 19
-jwt:
- header: Authorization
- expires_in_sec: 600 # 10 minutes
- secret: queenvictoria
- cookie: AUTH-TOKEN
-
logging:
level:
org.springframework.web: WARN
@@ -33,8 +27,22 @@ logging:
it.fabioformosa: DEBUG
quartz-manager:
+ security:
+ login-model:
+ form-login-enabled: true
+ userpwd-filter-enabled : false
+ jwt:
+ enabled: true
+ secret: "bibidibobidiboo"
+ expiration-in-sec: 28800 # 8 hours
+ header: "Authorization"
+ cookie: AUTH-TOKEN
jobClass: it.fabioformosa.quartzmanager.jobs.myjobs.SampleJob
- account:
- user: admin
- pwd: admin
-
\ No newline at end of file
+ accounts:
+ in-memory:
+ enabled: true
+ users:
+ - name: admin
+ password: admin
+ roles:
+ - ADMIN
\ No newline at end of file