guest session
This commit is contained in:
@@ -22,9 +22,10 @@ public class RefreshToken {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private LocalDateTime created;
|
private LocalDateTime created;
|
||||||
|
|
||||||
|
@Column(name = "session_id")
|
||||||
|
private String sessionId;
|
||||||
|
|
||||||
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
|
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
|
||||||
@JoinColumn(name = "user_id", nullable = false)
|
@JoinColumn(name = "user_id", nullable = false)
|
||||||
private User user;
|
private User user;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Inte
|
|||||||
|
|
||||||
Optional<RefreshToken> findByUserId(Integer userId);
|
Optional<RefreshToken> findByUserId(Integer userId);
|
||||||
|
|
||||||
|
Optional<RefreshToken> findByUserEmail(String email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,13 @@ public class JwtTokenProvider {
|
|||||||
this.jwtValidityInMilliseconds = jwtValidityInMilliseconds;
|
this.jwtValidityInMilliseconds = jwtValidityInMilliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateToken(@NonNull User user) {
|
public String generateToken(@NonNull User user, String sessionId) {
|
||||||
Map<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
claims.put(AuthenticationConstants.USER_ID, user.getId());
|
claims.put(AuthenticationConstants.USER_ID, user.getId());
|
||||||
claims.put(AuthenticationConstants.USERNAME, user.getUsername());
|
claims.put(AuthenticationConstants.USERNAME, user.getUsername());
|
||||||
claims.put(AuthenticationConstants.USER_EMAIL, user.getEmail());
|
claims.put(AuthenticationConstants.USER_EMAIL, user.getEmail());
|
||||||
claims.put(AuthenticationConstants.USER_REGISTRATION_STATUS, user.getRegistrationStatus().name());
|
claims.put(AuthenticationConstants.USER_REGISTRATION_STATUS, user.getRegistrationStatus().name());
|
||||||
|
claims.put(AuthenticationConstants.SESSION_ID, sessionId);
|
||||||
claims.put(AuthenticationConstants.LAST_UPDATE, LocalDateTime.now().toString());
|
claims.put(AuthenticationConstants.LAST_UPDATE, LocalDateTime.now().toString());
|
||||||
|
|
||||||
return createToken(claims, user.getEmail());
|
return createToken(claims, user.getEmail());
|
||||||
@@ -93,5 +94,11 @@ public class JwtTokenProvider {
|
|||||||
.signWith(secretKey, SignatureAlgorithm.HS512)
|
.signWith(secretKey, SignatureAlgorithm.HS512)
|
||||||
.compact();
|
.compact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSessionId(String token) {
|
||||||
|
Claims claims = getAllClaimsFromToken(token);
|
||||||
|
return claims.get(AuthenticationConstants.SESSION_ID, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.balex.rag.security.filter;
|
|||||||
|
|
||||||
import com.balex.rag.model.constants.ApiErrorMessage;
|
import com.balex.rag.model.constants.ApiErrorMessage;
|
||||||
import com.balex.rag.security.JwtTokenProvider;
|
import com.balex.rag.security.JwtTokenProvider;
|
||||||
|
import com.balex.rag.service.impl.RefreshTokenServiceImpl;
|
||||||
import io.jsonwebtoken.ExpiredJwtException;
|
import io.jsonwebtoken.ExpiredJwtException;
|
||||||
import io.jsonwebtoken.MalformedJwtException;
|
import io.jsonwebtoken.MalformedJwtException;
|
||||||
import io.jsonwebtoken.SignatureException;
|
import io.jsonwebtoken.SignatureException;
|
||||||
@@ -36,6 +37,7 @@ public class JwtRequestFilter extends OncePerRequestFilter {
|
|||||||
private static final String REGISTER_PATH = "/auth/register";
|
private static final String REGISTER_PATH = "/auth/register";
|
||||||
|
|
||||||
private final JwtTokenProvider jwtTokenProvider;
|
private final JwtTokenProvider jwtTokenProvider;
|
||||||
|
private final RefreshTokenServiceImpl refreshTokenService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(
|
protected void doFilterInternal(
|
||||||
@@ -61,8 +63,16 @@ public class JwtRequestFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
Optional<String> emailOpt = Optional.ofNullable(jwtTokenProvider.getUsername(jwt));
|
Optional<String> emailOpt = Optional.ofNullable(jwtTokenProvider.getUsername(jwt));
|
||||||
Optional<String> userIdOpt = Optional.ofNullable(jwtTokenProvider.getUserId(jwt));
|
Optional<String> userIdOpt = Optional.ofNullable(jwtTokenProvider.getUserId(jwt));
|
||||||
|
String sessionId = jwtTokenProvider.getSessionId(jwt);
|
||||||
|
|
||||||
if (emailOpt.isPresent() && userIdOpt.isPresent()) {
|
if (emailOpt.isPresent() && userIdOpt.isPresent()) {
|
||||||
|
// Check session validity
|
||||||
|
Optional<String> activeSessionId = refreshTokenService.getSessionIdByEmail(emailOpt.get());
|
||||||
|
if (activeSessionId.isEmpty() || !activeSessionId.get().equals(sessionId)) {
|
||||||
|
sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "SESSION_INVALIDATED");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
List<SimpleGrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority(USER_ROLE));
|
List<SimpleGrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority(USER_ROLE));
|
||||||
|
|
||||||
@@ -75,7 +85,6 @@ public class JwtRequestFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (ExpiredJwtException e) {
|
} catch (ExpiredJwtException e) {
|
||||||
handleTokenExpiration(requestURI, jwt, response);
|
handleTokenExpiration(requestURI, jwt, response);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
.orElseThrow(() -> new InvalidDataException(ApiErrorMessage.INVALID_USER_OR_PASSWORD.getMessage()));
|
.orElseThrow(() -> new InvalidDataException(ApiErrorMessage.INVALID_USER_OR_PASSWORD.getMessage()));
|
||||||
|
|
||||||
RefreshToken refreshToken = refreshTokenService.generateOrUpdateRefreshToken(user);
|
RefreshToken refreshToken = refreshTokenService.generateOrUpdateRefreshToken(user);
|
||||||
String token = jwtTokenProvider.generateToken(user);
|
String token = jwtTokenProvider.generateToken(user, refreshToken.getSessionId());
|
||||||
UserProfileDTO userProfileDTO = userMapper.toUserProfileDto(user, token, refreshToken.getToken());
|
UserProfileDTO userProfileDTO = userMapper.toUserProfileDto(user, token, refreshToken.getToken());
|
||||||
userProfileDTO.setToken(token);
|
userProfileDTO.setToken(token);
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
RefreshToken refreshToken = refreshTokenService.validateAndRefreshToken(refreshTokenValue);
|
RefreshToken refreshToken = refreshTokenService.validateAndRefreshToken(refreshTokenValue);
|
||||||
User user = refreshToken.getUser();
|
User user = refreshToken.getUser();
|
||||||
|
|
||||||
String accessToken = jwtTokenProvider.generateToken(user);
|
String accessToken = jwtTokenProvider.generateToken(user, refreshToken.getSessionId());
|
||||||
|
|
||||||
return RagResponse.createSuccessfulWithNewToken(
|
return RagResponse.createSuccessfulWithNewToken(
|
||||||
userMapper.toUserProfileDto(user, accessToken, refreshToken.getToken())
|
userMapper.toUserProfileDto(user, accessToken, refreshToken.getToken())
|
||||||
@@ -74,7 +74,6 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RagResponse<UserProfileDTO> registerUser(@NotNull RegistrationUserRequest request) {
|
public RagResponse<UserProfileDTO> registerUser(@NotNull RegistrationUserRequest request) {
|
||||||
|
|
||||||
accessValidator.validateNewUser(
|
accessValidator.validateNewUser(
|
||||||
request.getUsername(),
|
request.getUsername(),
|
||||||
request.getEmail(),
|
request.getEmail(),
|
||||||
@@ -87,7 +86,7 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
userRepository.save(newUser);
|
userRepository.save(newUser);
|
||||||
|
|
||||||
RefreshToken refreshToken = refreshTokenService.generateOrUpdateRefreshToken(newUser);
|
RefreshToken refreshToken = refreshTokenService.generateOrUpdateRefreshToken(newUser);
|
||||||
String token = jwtTokenProvider.generateToken(newUser);
|
String token = jwtTokenProvider.generateToken(newUser, refreshToken.getSessionId());
|
||||||
UserProfileDTO userProfileDTO = userMapper.toUserProfileDto(newUser, token, refreshToken.getToken());
|
UserProfileDTO userProfileDTO = userMapper.toUserProfileDto(newUser, token, refreshToken.getToken());
|
||||||
userProfileDTO.setToken(token);
|
userProfileDTO.setToken(token);
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@@ -21,10 +22,12 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RefreshToken generateOrUpdateRefreshToken(User user) {
|
public RefreshToken generateOrUpdateRefreshToken(User user) {
|
||||||
|
String sessionId = ApiUtils.generateUuidWithoutDash();
|
||||||
return refreshTokenRepository.findByUserId(user.getId())
|
return refreshTokenRepository.findByUserId(user.getId())
|
||||||
.map(refreshToken -> {
|
.map(refreshToken -> {
|
||||||
refreshToken.setCreated(LocalDateTime.now());
|
refreshToken.setCreated(LocalDateTime.now());
|
||||||
refreshToken.setToken(ApiUtils.generateUuidWithoutDash());
|
refreshToken.setToken(ApiUtils.generateUuidWithoutDash());
|
||||||
|
refreshToken.setSessionId(sessionId);
|
||||||
return refreshTokenRepository.save(refreshToken);
|
return refreshTokenRepository.save(refreshToken);
|
||||||
})
|
})
|
||||||
.orElseGet(() -> {
|
.orElseGet(() -> {
|
||||||
@@ -32,6 +35,7 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
|
|||||||
newToken.setUser(user);
|
newToken.setUser(user);
|
||||||
newToken.setCreated(LocalDateTime.now());
|
newToken.setCreated(LocalDateTime.now());
|
||||||
newToken.setToken(ApiUtils.generateUuidWithoutDash());
|
newToken.setToken(ApiUtils.generateUuidWithoutDash());
|
||||||
|
newToken.setSessionId(sessionId);
|
||||||
return refreshTokenRepository.save(newToken);
|
return refreshTokenRepository.save(newToken);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -46,5 +50,8 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
|
|||||||
return refreshTokenRepository.save(refreshToken);
|
return refreshTokenRepository.save(refreshToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<String> getSessionIdByEmail(String email) {
|
||||||
|
return refreshTokenRepository.findByUserEmail(email)
|
||||||
|
.map(RefreshToken::getSessionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public final class AuthenticationConstants {
|
|||||||
public static final String USER_EMAIL = "email";
|
public static final String USER_EMAIL = "email";
|
||||||
public static final String USER_REGISTRATION_STATUS = "userRegistrationStatus";
|
public static final String USER_REGISTRATION_STATUS = "userRegistrationStatus";
|
||||||
public static final String LAST_UPDATE = "lastUpdate";
|
public static final String LAST_UPDATE = "lastUpdate";
|
||||||
|
public static final String SESSION_ID = "sessionId";
|
||||||
public static final String ACCESS_KEY_HEADER_NAME = "key";
|
public static final String ACCESS_KEY_HEADER_NAME = "key";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user