Some refactoring

This commit is contained in:
Armin Wolf 2024-04-22 11:03:18 +02:00
parent e94d23d760
commit 1aa2cf221c
5 changed files with 55 additions and 32 deletions

View File

@ -10,9 +10,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtDecoder;
@ -21,35 +22,62 @@ import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
import org.springframework.stereotype.Component;
import java.net.MalformedURLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Component
public class UserAuthenticationProvider {
private static Logger LOG = LoggerFactory.getLogger(UserAuthenticationProvider.class);
public class AuthenticationProvider {
private static Logger LOG = LoggerFactory.getLogger(AuthenticationProvider.class);
public static final String ROLES = "roles";
public static final String USERNAME = "username";
@Value("${security.jwt.token.issuer:https://armin-wolf.de}")
private String issuer;
private final PasswordEncoder passwordEncoder;
private final UserService userService;
private final JwtDecoder jwtDecoder;
private final JwtEncoder jwtEncoder;
private final UserService userService;
private final JwtDecoder jwtDecoder;
private final JwtEncoder jwtEncoder;
public Authentication validateToken(final String token) throws MalformedURLException {
Jwt decode = jwtDecoder.decode(token);
if (!decode.getIssuer().toString().equals(issuer)) {
public Authentication validateToken(final String token) {
Jwt decodedToken = jwtDecoder.decode(token);
// check validity of token
if (Objects.isNull(decodedToken) || !isValid(decodedToken)) {
throw new AppException("Invalid token", HttpStatus.UNAUTHORIZED);
}
User user = userService.findByUsername(decode.getClaim(USERNAME))
.orElseThrow(() -> new AppException("User not found", HttpStatus.BAD_REQUEST));
return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
Optional<User> byUsername = userService.findByUsername(decodedToken.getClaim(USERNAME));
if (byUsername.isEmpty()) {
throw new AppException("User not found", HttpStatus.BAD_REQUEST);
} else {
User user = byUsername.get();
return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
}
}
private boolean isValid(final Jwt decodedToken) {
if (!Objects.equals(decodedToken.getIssuer().toString(), issuer)) {
LOG.warn("Invalid issuer: '{}'.", decodedToken.getIssuer());
return false;
}
if (Objects.isNull(decodedToken.getExpiresAt()) || decodedToken.getExpiresAt().isAfter(LocalDateTime.now().toInstant(ZoneOffset.UTC))) {
LOG.warn("Token expired: '{}'.", decodedToken.getExpiresAt());
return false;
}
return true;
}
@ -65,10 +93,8 @@ public class UserAuthenticationProvider {
.issuedAt(now.toInstant())
.build();
LOG.info("Creating token for user: {}", user.getUsername());
LOG.info("Creating token for user: '{}'.", user.getUsername());
JwtEncoderParameters jwtEncoderParameters = JwtEncoderParameters.from(jwtClaimsSet);
return jwtEncoder.encode(jwtEncoderParameters).getTokenValue();
}
}

View File

@ -15,11 +15,11 @@ import java.util.Objects;
@AllArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
public static final String BEARER_TOKEN_PREFIX = "Bearer ";
public static final String AUTHORIZATION = "Authorization";
public static final int BEARER_TOKEN_START_INDEX = 7;
public static final String BEARER_TOKEN_PREFIX = "Bearer ";
public static final String AUTHORIZATION = "Authorization";
public static final int BEARER_TOKEN_START_INDEX = 7;
protected final UserAuthenticationProvider userAuthenticationProvider;
protected final AuthenticationProvider authenticationProvider;
@Override
@ -29,9 +29,8 @@ public class JwtAuthFilter extends OncePerRequestFilter {
String authorization = request.getHeader(AUTHORIZATION);
if (Objects.nonNull(authorization) && authorization.startsWith(BEARER_TOKEN_PREFIX)) {
String token = authorization.substring(BEARER_TOKEN_START_INDEX);
Authentication authentication = userAuthenticationProvider.validateToken(token);
String token = authorization.substring(BEARER_TOKEN_START_INDEX);
Authentication authentication = authenticationProvider.validateToken(token);
try {
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (RuntimeException e) {

View File

@ -18,13 +18,11 @@ public class TokenConfig {
private final RSAKeyProvider keyProvider;
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withPublicKey(keyProvider.getPublicKey()).build();
}
@Bean
public JwtEncoder jwtEncoder() {
RSAKey rsaKey = new RSAKey.Builder(keyProvider.getPublicKey()).privateKey(keyProvider.getPrivateKey()).build();

View File

@ -24,7 +24,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
public class WebConfig {
private final UserAuthenticationEntryPoint userAuthenticationEntryPoint;
private final UserAuthenticationProvider userAuthenticationProvider;
private final AuthenticationProvider authenticationProvider;
@ -33,7 +33,7 @@ public class WebConfig {
http.csrf(AbstractHttpConfigurer::disable)
.cors(AbstractHttpConfigurer::disable)
.exceptionHandling(exceptionHandling -> exceptionHandling.authenticationEntryPoint(userAuthenticationEntryPoint))
.addFilterBefore(new JwtAuthFilter(userAuthenticationProvider), BasicAuthenticationFilter.class)
.addFilterBefore(new JwtAuthFilter(authenticationProvider), BasicAuthenticationFilter.class)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests((requests) -> requests
.requestMatchers(HttpMethod.POST, "/login", "/register").permitAll()

View File

@ -1,6 +1,6 @@
package de.arminwolf.services;
import de.arminwolf.configs.UserAuthenticationProvider;
import de.arminwolf.configs.AuthenticationProvider;
import de.arminwolf.exceptions.AppException;
import de.arminwolf.models.User;
import de.arminwolf.models.dto.LoginRequestDTO;
@ -21,8 +21,8 @@ public class AuthenticationService {
private final UserService userService;
private final UserAuthenticationProvider userAuthenticationProvider;
private final PasswordEncoder passwordEncoder;
private final AuthenticationProvider authenticationProvider;
private final PasswordEncoder passwordEncoder;
private final RoleRepository roleRepository;
@ -34,7 +34,7 @@ public class AuthenticationService {
public UserDTO login(LoginRequestDTO loginRequestDTO) {
UserDTO userDTO = userService.login(loginRequestDTO.getUsername(), loginRequestDTO.getPassword());
userDTO.setToken(userAuthenticationProvider.createToken(userDTO));
userDTO.setToken(authenticationProvider.createToken(userDTO));
return userDTO;
}
@ -52,7 +52,7 @@ public class AuthenticationService {
// convert the latest user to a userDTO
final UserDTO userDTO = userMapper.userToUserDTO(user);
userDTO.setToken(userAuthenticationProvider.createToken(userDTO));
userDTO.setToken(authenticationProvider.createToken(userDTO));
return userDTO;
}
}