diff --git a/skill-tree/src/main/java/com/RDS/skilltree/Authentication/UserAuthenticationToken.java b/skill-tree/src/main/java/com/RDS/skilltree/Authentication/UserAuthenticationToken.java index 79586176..49758410 100644 --- a/skill-tree/src/main/java/com/RDS/skilltree/Authentication/UserAuthenticationToken.java +++ b/skill-tree/src/main/java/com/RDS/skilltree/Authentication/UserAuthenticationToken.java @@ -6,12 +6,11 @@ import java.util.UUID; public class UserAuthenticationToken extends AbstractAuthenticationToken { -private final String userId; + private final UserModel user; - - public UserAuthenticationToken(String userId) { + public UserAuthenticationToken(UserModel user) { super(null); - this.userId = userId; + this.user = user; setAuthenticated(true); } @@ -22,7 +21,7 @@ public Object getCredentials() { @Override public Object getPrincipal() { - return userId; + return user; } @Override diff --git a/skill-tree/src/main/java/com/RDS/skilltree/Config/SecurityConfig.java b/skill-tree/src/main/java/com/RDS/skilltree/Config/SecurityConfig.java index 00609377..46f15a73 100644 --- a/skill-tree/src/main/java/com/RDS/skilltree/Config/SecurityConfig.java +++ b/skill-tree/src/main/java/com/RDS/skilltree/Config/SecurityConfig.java @@ -30,10 +30,10 @@ public SecurityConfig(UserService userService, AuthEntryPoint authEntryPoint) { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth->auth - .requestMatchers("/{userId}").access(new WebExpressionAuthorizationManager("#userId == authentication.userId")) // user self details .requestMatchers("/**").authenticated()) .exceptionHandling(ex->ex.authenticationEntryPoint(authEntryPoint)) - .sessionManagement(session->session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); + .sessionManagement(session -> session.maximumSessions(1)); + http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } diff --git a/skill-tree/src/main/java/com/RDS/skilltree/Filters/JWTAuthenticationFilter.java b/skill-tree/src/main/java/com/RDS/skilltree/Filters/JWTAuthenticationFilter.java index 7f8b5fe0..6d0fe1d0 100644 --- a/skill-tree/src/main/java/com/RDS/skilltree/Filters/JWTAuthenticationFilter.java +++ b/skill-tree/src/main/java/com/RDS/skilltree/Filters/JWTAuthenticationFilter.java @@ -18,6 +18,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; +import javax.security.sasl.AuthenticationException; import java.io.IOException; import java.net.URL; import java.util.concurrent.CompletableFuture; @@ -44,36 +45,34 @@ public JWTAuthenticationFilter(UserService userService){ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = getJWTFromRequest(request); + try { if (StringUtils.hasText(token) && jwtUtils.validateToken(token)) { String rdsUserId = jwtUtils.getRDSUserId(token); -// Object sc = request.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY); -// -// if(sc != null) -// System.out.println(((SecurityContext) sc).getAuthentication()); - - /* - * get user data from RDS using the userId - * */ - UserModel userModel; +if(SecurityContextHolder.getContext().getAuthentication() == null) { + UserModel userModel; - CompletableFuture userResponse = fetchAPI.getRDSUserData(rdsUserId); - CompletableFuture.anyOf(userResponse).join(); - Response rdsUserResponse = userResponse.get(); - UserDRO userDRO = UserDRO.builder() - .rdsUserId(rdsUserId) - .firstName(rdsUserResponse.getUser().getFirst_name()) - .lastName(rdsUserResponse.getUser().getLast_name()) - .imageUrl(new URL(rdsUserResponse.getUser().getPicture().getUrl())) - .role(UserRole.USER) - .build(); - userModel = UserDRO.toModel(userDRO); + CompletableFuture userResponse = fetchAPI.getRDSUserData(rdsUserId); + if (userResponse == null) { // (3) + throw new AuthenticationException("could not login"); + } + CompletableFuture.anyOf(userResponse).join(); + Response rdsUserResponse = userResponse.get(); + UserDRO userDRO = UserDRO.builder() + .rdsUserId(rdsUserId) + .firstName(rdsUserResponse.getUser().getFirst_name()) + .lastName(rdsUserResponse.getUser().getLast_name()) + .imageUrl(new URL(rdsUserResponse.getUser().getPicture().getUrl())) + .role(UserRole.USER) + .build(); + userModel = UserDRO.toModel(userDRO); - UserAuthenticationToken authentication = new UserAuthenticationToken(rdsUserId); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); + UserAuthenticationToken authentication = new UserAuthenticationToken(userModel); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); +} } } catch (Exception e) { log.error("Error in fetching the user details, error : {}", e.getMessage(), e); diff --git a/skill-tree/src/main/java/com/RDS/skilltree/User/UserDRO.java b/skill-tree/src/main/java/com/RDS/skilltree/User/UserDRO.java index 26e747de..0cd2366f 100644 --- a/skill-tree/src/main/java/com/RDS/skilltree/User/UserDRO.java +++ b/skill-tree/src/main/java/com/RDS/skilltree/User/UserDRO.java @@ -61,8 +61,7 @@ public static UserModel compareAndUpdateModel(UserModel user, UserDRO userDRO) { if (userDRO.getRole() != null) { user.setRole(user.getRole()); } - user.setUpdatedAt(Instant.now()); - user.setUpdatedBy(user); + return user; } } diff --git a/skill-tree/src/main/java/com/RDS/skilltree/User/UserModel.java b/skill-tree/src/main/java/com/RDS/skilltree/User/UserModel.java index 51780810..59423dcd 100644 --- a/skill-tree/src/main/java/com/RDS/skilltree/User/UserModel.java +++ b/skill-tree/src/main/java/com/RDS/skilltree/User/UserModel.java @@ -24,7 +24,7 @@ @NoArgsConstructor @AllArgsConstructor @Table(name = "Users") -public abstract class UserModel implements UserDetails { +public class UserModel { @Id @GeneratedValue @Column(name = "id", columnDefinition = "BINARY(16)") @@ -51,18 +51,18 @@ public abstract class UserModel implements UserDetails { @JoinTable(name = "user_skill", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "skill_id")) private Set skills; - @Override - public Collection getAuthorities() { - return List.of(new SimpleGrantedAuthority(role.name())); - } - - @Override - public String getUsername() { - return firstName +" "+ lastName; - } - - @Override - public boolean isEnabled() { - return true; - } +// @Override +// public Collection getAuthorities() { +// return List.of(new SimpleGrantedAuthority(role.name())); +// } +// +// @Override +// public String getUsername() { +// return firstName +" "+ lastName; +// } +// +// @Override +// public boolean isEnabled() { +// return true; +// } } diff --git a/skill-tree/src/main/java/com/RDS/skilltree/utils/JWTUtils.java b/skill-tree/src/main/java/com/RDS/skilltree/utils/JWTUtils.java index 904390af..2a5b05e0 100644 --- a/skill-tree/src/main/java/com/RDS/skilltree/utils/JWTUtils.java +++ b/skill-tree/src/main/java/com/RDS/skilltree/utils/JWTUtils.java @@ -1,8 +1,10 @@ package com.RDS.skilltree.utils; import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; import jakarta.annotation.PostConstruct; +import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; @@ -16,6 +18,8 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; +import java.util.Date; +import java.util.function.Function; @Component @Slf4j @@ -48,13 +52,19 @@ private RSAPublicKey convertToRSAPublicKey(String publicKeyString) throws Except private Claims extractAllClaims (String token) throws Exception{ return Jwts - .parserBuilder() + .parser() .setSigningKey(convertToRSAPublicKey(publicRDSKeyString)) - .build() .parseClaimsJws(token) .getBody(); } + private Boolean isTokenExpired(String token) throws Exception { + Claims claims = extractAllClaims(token); + + final Date expiration = claims.get("exp", Date.class); + return expiration.before(new Date()); + } + public String getRDSUserId(String token) throws Exception { Claims claims = extractAllClaims(token); String temp = claims.get("userId", String.class); @@ -63,10 +73,12 @@ public String getRDSUserId(String token) throws Exception { public boolean validateToken(String token) throws Exception { //TODO check for the case where token is expired try { - Jwts.parser().setSigningKey(convertToRSAPublicKey(publicRDSKeyString)).parseClaimsJws(token); - return true; + return (!isTokenExpired(token)); + } catch (InvalidKeySpecException e) { throw new RuntimeException(e); + }catch (ExpiredJwtException e) { + throw new AuthenticationCredentialsNotFoundException("Given jwt token is expired !!"); } catch (Exception e) { throw new AuthenticationCredentialsNotFoundException("Invalid JWT"); } diff --git a/skill-tree/src/main/resources/application.properties b/skill-tree/src/main/resources/application.properties index 693cd87d..eb869f2c 100644 --- a/skill-tree/src/main/resources/application.properties +++ b/skill-tree/src/main/resources/application.properties @@ -8,4 +8,4 @@ jwt.rds.public.key=${RDS_PUBLIC_KEY} API_V1_PREFIX=/api/v1 spring.datasource.version=8.1.0 management.endpoints.web.exposure.include=health,info,metrics - +server.servlet.session.timeout=3600