master
tszyszkowski 2022-02-28 21:43:20 +01:00
parent 2d2a9e8909
commit e87736fd26
6 changed files with 224 additions and 0 deletions

View File

@ -29,6 +29,11 @@
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>pl.adaptiveapps</groupId>
<artifactId>service-kafka-model</artifactId>

View File

@ -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);
}
}

View File

@ -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!");
}
}
}

View File

@ -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);
}
}

View File

@ -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<? extends GrantedAuthority> 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;
}
}

View File

@ -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);
}
}