From e87736fd26a400711597a0e774c8b54c3706fec0 Mon Sep 17 00:00:00 2001 From: tszyszkowski Date: Mon, 28 Feb 2022 21:43:20 +0100 Subject: [PATCH] ... --- pom.xml | 5 ++ .../serviceexternalserver/auth/ExtToken.java | 44 +++++++++++++++ .../auth/ExtTokenAuthenticationProvider.java | 36 +++++++++++++ .../ExtTokenAuthenticationTokenFilter.java | 36 +++++++++++++ .../serviceexternalserver/auth/ExtUser.java | 49 +++++++++++++++++ .../config/SecurityConfig.java | 54 +++++++++++++++++++ 6 files changed, 224 insertions(+) create mode 100644 src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtToken.java create mode 100644 src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtTokenAuthenticationProvider.java create mode 100644 src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtTokenAuthenticationTokenFilter.java create mode 100644 src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtUser.java create mode 100644 src/main/java/pl/adaptiveapps/serviceexternalserver/config/SecurityConfig.java diff --git a/pom.xml b/pom.xml index 39b28cc..3ce279d 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,11 @@ org.springframework.kafka spring-kafka + + commons-codec + commons-codec + 1.15 + pl.adaptiveapps service-kafka-model diff --git a/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtToken.java b/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtToken.java new file mode 100644 index 0000000..f844f6b --- /dev/null +++ b/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtToken.java @@ -0,0 +1,44 @@ +package pl.adaptiveapps.serviceexternalserver.auth; + +import org.apache.commons.codec.digest.DigestUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; + +import java.sql.Timestamp; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Date; +import java.util.TimeZone; + +public class ExtToken extends UsernamePasswordAuthenticationToken { + private static final Logger logger = LoggerFactory.getLogger(ExtToken.class); + String token; + String timestamp; + + public ExtToken(String token, String timestamp) { + super(null, null); + this.token = token; + this.timestamp = timestamp; + } + + public boolean validate(String clientToken) { + String sha3 = DigestUtils.sha3_512Hex(clientToken + timestamp); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); + df.setTimeZone(tz); + try { + Date parsedTimestamp = df.parse(timestamp); + Long timeDiff = parsedTimestamp.getTime() - Timestamp.from(Instant.now()).getTime(); + System.out.println("Time diff: " + timeDiff); + if (Math.abs(timeDiff) > 15000) { + return false; + } + } catch (ParseException e) { + e.printStackTrace(); + } + return token.equals(sha3); + } +} diff --git a/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtTokenAuthenticationProvider.java b/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtTokenAuthenticationProvider.java new file mode 100644 index 0000000..8402648 --- /dev/null +++ b/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtTokenAuthenticationProvider.java @@ -0,0 +1,36 @@ +package pl.adaptiveapps.serviceexternalserver.auth; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.session.SessionAuthenticationException; +import org.springframework.stereotype.Component; + +@Component +public class ExtTokenAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { + + private static final Logger logger = LoggerFactory.getLogger(ExtTokenAuthenticationProvider.class); + + @Value( "${ext.client.token}" ) + private String extToken; + + @Override + protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException { + } + + @Override + protected UserDetails retrieveUser(String s, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException { + ExtToken token = (ExtToken) usernamePasswordAuthenticationToken; + if (token.validate(extToken)) { + logger.info("Token validated"); + return new ExtUser(); + } else { + logger.info("Token not valid"); + throw new SessionAuthenticationException("Invalid token!"); + } + } +} diff --git a/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtTokenAuthenticationTokenFilter.java b/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtTokenAuthenticationTokenFilter.java new file mode 100644 index 0000000..f5e9d4e --- /dev/null +++ b/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtTokenAuthenticationTokenFilter.java @@ -0,0 +1,36 @@ +package pl.adaptiveapps.serviceexternalserver.auth; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class ExtTokenAuthenticationTokenFilter extends AbstractAuthenticationProcessingFilter { + private final static String TOKEN_HEADER = "Authorization"; + private final static String TIMESTAMP_HEADER = "X-Timestamp"; + private static final Logger logger = LoggerFactory.getLogger(ExtTokenAuthenticationTokenFilter.class); + + public ExtTokenAuthenticationTokenFilter() { + super("/api/**"); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException { + String authToken = httpServletRequest.getHeader(TOKEN_HEADER); + String timestamp = httpServletRequest.getHeader(TIMESTAMP_HEADER); + return getAuthenticationManager().authenticate(new ExtToken(authToken, timestamp)); + } + + @Override + public void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { + super.successfulAuthentication(request, response, chain, authResult); + chain.doFilter(request, response); + } +} diff --git a/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtUser.java b/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtUser.java new file mode 100644 index 0000000..c0c0dd1 --- /dev/null +++ b/src/main/java/pl/adaptiveapps/serviceexternalserver/auth/ExtUser.java @@ -0,0 +1,49 @@ +package pl.adaptiveapps.serviceexternalserver.auth; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.List; + +public class ExtUser implements UserDetails { + @Override + public Collection getAuthorities() { + return List.of(new GrantedAuthority() { + @Override + public String getAuthority() { + return "ADMIN"; + } + }); + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return "EXT"; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/pl/adaptiveapps/serviceexternalserver/config/SecurityConfig.java b/src/main/java/pl/adaptiveapps/serviceexternalserver/config/SecurityConfig.java new file mode 100644 index 0000000..99baf12 --- /dev/null +++ b/src/main/java/pl/adaptiveapps/serviceexternalserver/config/SecurityConfig.java @@ -0,0 +1,54 @@ +package pl.adaptiveapps.serviceexternalserver.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +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.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import pl.adaptiveapps.serviceexternalserver.auth.ExtTokenAuthenticationProvider; +import pl.adaptiveapps.serviceexternalserver.auth.ExtTokenAuthenticationTokenFilter; + +import java.util.Collections; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + private final ExtTokenAuthenticationProvider extTokenAuthenticationProvider; + + public SecurityConfig(ExtTokenAuthenticationProvider extTokenAuthenticationProvider) { + this.extTokenAuthenticationProvider = extTokenAuthenticationProvider; + } + + @Override + protected AuthenticationManager authenticationManager() { + return new ProviderManager(Collections.singletonList(extTokenAuthenticationProvider)); + } + + private ExtTokenAuthenticationTokenFilter authenticationTokenFilterBean() { + ExtTokenAuthenticationTokenFilter authenticationTokenFilter = new ExtTokenAuthenticationTokenFilter(); + authenticationTokenFilter.setAuthenticationManager(authenticationManager()); + authenticationTokenFilter.setAuthenticationSuccessHandler((request, response, authentication) -> { + }); + return authenticationTokenFilter; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() + .authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll() + .antMatchers("/api/**").authenticated() + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + http + .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); + } + +}