Skip to content

Commit

Permalink
Feat(#171): 리프레시토큰 로직 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
mingeun0507 committed May 25, 2023
1 parent 7876b26 commit 4e4d162
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com._8attery.seesaw.controller.auth;

import com._8attery.seesaw.annotation.ClientIp;
import com._8attery.seesaw.dto.api.request.EmailRequestDto;
import com._8attery.seesaw.dto.auth.request.LoginRequestDto;
import com._8attery.seesaw.dto.auth.request.RefreshTokenRequestDto;
Expand All @@ -21,19 +22,19 @@ public class AuthController {
private final AuthServiceImpl authService;

@PostMapping("/login")
public ResponseEntity<LoginResponseDto> login(@Valid @RequestBody LoginRequestDto loginRequestDto) {
public ResponseEntity<LoginResponseDto> login(@Valid @RequestBody LoginRequestDto loginRequestDto, @ClientIp String clientIp) {
if (loginRequestDto.getProvider().equalsIgnoreCase("APPLE")) {
return ResponseEntity.ok(authService.appleLogin(loginRequestDto));
return ResponseEntity.ok(authService.appleLogin(loginRequestDto, clientIp));
} else if (loginRequestDto.getProvider().equalsIgnoreCase("KAKAO")) {
return ResponseEntity.ok(authService.kakaoLogin(loginRequestDto));
return ResponseEntity.ok(authService.kakaoLogin(loginRequestDto, clientIp));
} else {
throw new IllegalArgumentException("Provider값이 KAKAO 또는 APPLE이 아닙니다.");
}
}

@PostMapping("/regenerate-token")
public ResponseEntity<LoginResponseDto> regenerateAccessToken(@Valid @RequestBody RefreshTokenRequestDto refreshTokenRequestDto) {
return ResponseEntity.ok(authService.regenerateAccessToken(refreshTokenRequestDto));
public ResponseEntity<LoginResponseDto> regenerateAccessToken(@Valid @RequestBody RefreshTokenRequestDto refreshTokenRequestDto, @ClientIp String clientIp) {
return ResponseEntity.ok(authService.regenerateAccessToken(refreshTokenRequestDto, clientIp));
}

@PostMapping("/test/generate-token")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ public interface AuthService {
User findUserById(Long userId);

// 비즈니스 로직
LoginResponseDto appleLogin(LoginRequestDto loginRequestDto);
LoginResponseDto appleLogin(LoginRequestDto loginRequestDto, String clientIp);

LoginResponseDto regenerateAccessToken(RefreshTokenRequestDto refreshTokenRequestDto);
LoginResponseDto regenerateAccessToken(RefreshTokenRequestDto refreshTokenRequestDto, String clientIp);

LoginResponseDto kakaoLogin(LoginRequestDto loginRequestDto);
LoginResponseDto kakaoLogin(LoginRequestDto loginRequestDto, String clientIp);

LoginResponseDto getLoginResponseDto(User user);
LoginResponseDto getLoginResponseDto(User user, String clientIp);

LoginResponseDto generateAccessTokenByUserId(Long userId);

Expand Down
46 changes: 35 additions & 11 deletions src/main/java/com/_8attery/seesaw/service/auth/AuthServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public User findUserById(Long userId) {
}

@Override
public LoginResponseDto appleLogin(LoginRequestDto loginRequestDto) {
public LoginResponseDto appleLogin(LoginRequestDto loginRequestDto, String clientIp) {
String email = appleOAuthUserProvider.getEmailFromToken(loginRequestDto.getIdToken());
log.info("Apple Login Request Email : {}", email);
Optional<User> existingUser = userRepository.findByEmail(email);
Expand All @@ -67,33 +67,57 @@ public LoginResponseDto appleLogin(LoginRequestDto loginRequestDto) {
.build());
}

return getLoginResponseDto(targetUser);
return getLoginResponseDto(targetUser, clientIp);
}

@Override
public LoginResponseDto regenerateAccessToken(RefreshTokenRequestDto refreshTokenRequestDto) {
public LoginResponseDto regenerateAccessToken(RefreshTokenRequestDto refreshTokenRequestDto, String clientIp) {
String refreshToken = refreshTokenRequestDto.getRefreshToken();
Long userId = jwtTokenUtil.getUserIdFromRefreshToken(refreshToken);
String existingRefreshToken = redisTemplate.opsForValue().get(userId.toString()); // Redis에 저장된 refreshToken인지 확인
String existingIp = redisTemplate.opsForValue().get(refreshToken); // Redis에 저장된 refreshToken인지 확인

if (existingRefreshToken != null && !existingRefreshToken.equals(refreshToken)) { // refreshToken이 같은 지 검증
if (existingIp == null) { // refreshToken이 같은 지 검증
throw new InvalidTokenException("유효하지 않은 Refresh Token입니다.");
} else if (!existingIp.equals(refreshToken)) { // refreshToken이 같은 지 검증
throw new InvalidTokenException("다른 IP에서 접속했습니다. 다시 로그인해주세요.");
}

Long userId = jwtTokenUtil.getUserIdFromRefreshToken(refreshToken);
User existingUser = findUserById(userId);
String newAccessToken = jwtTokenUtil.generateAccessToken(existingUser.getId(), existingUser.getEmail(), existingUser.getRole());
String newRefreshToken = jwtTokenUtil.generateRefreshToken(existingUser.getId(), existingUser.getEmail());

redisTemplate.opsForValue().set(userId.toString(), newRefreshToken, REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.SECONDS); // Redis에 저장 (key: userId, value: refreshToken)
redisTemplate.opsForValue().set(newRefreshToken, clientIp, REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.SECONDS); // Redis에 저장 (key: userId, value: refreshToken)

return LoginResponseDto.builder()
.accessToken(newAccessToken)
.refreshToken(newRefreshToken)
.build();
}

// @Override
// public LoginResponseDto regenerateAccessToken(RefreshTokenRequestDto refreshTokenRequestDto) {
// String refreshToken = refreshTokenRequestDto.getRefreshToken();
// Long userId = jwtTokenUtil.getUserIdFromRefreshToken(refreshToken);
// String existingRefreshToken = redisTemplate.opsForValue().get(userId.toString()); // Redis에 저장된 refreshToken인지 확인
//
// if (existingRefreshToken != null && !existingRefreshToken.equals(refreshToken)) { // refreshToken이 같은 지 검증
// throw new InvalidTokenException("유효하지 않은 Refresh Token입니다.");
// }
//
// User existingUser = findUserById(userId);
// String newAccessToken = jwtTokenUtil.generateAccessToken(existingUser.getId(), existingUser.getEmail(), existingUser.getRole());
// String newRefreshToken = jwtTokenUtil.generateRefreshToken(existingUser.getId(), existingUser.getEmail());
//
// redisTemplate.opsForValue().set(userId.toString(), newRefreshToken, REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.SECONDS); // Redis에 저장 (key: userId, value: refreshToken)
//
// return LoginResponseDto.builder()
// .accessToken(newAccessToken)
// .refreshToken(newRefreshToken)
// .build();
// }

@Override
public LoginResponseDto kakaoLogin(LoginRequestDto loginRequestDto) {
public LoginResponseDto kakaoLogin(LoginRequestDto loginRequestDto, String clientIp) {
String email = oAuthOidcHelper.getPayloadFromIdToken(loginRequestDto.getIdToken()).getEmail();
log.info("Kakao Login Request Email : {}", email);

Expand All @@ -113,14 +137,14 @@ public LoginResponseDto kakaoLogin(LoginRequestDto loginRequestDto) {
.build());
}

return getLoginResponseDto(targetUser);
return getLoginResponseDto(targetUser, clientIp);
}

@Override
public LoginResponseDto getLoginResponseDto(User targetUser) {
public LoginResponseDto getLoginResponseDto(User targetUser, String clientIp) {
String accessToken = jwtTokenUtil.generateAccessToken(targetUser.getId(), targetUser.getEmail(), targetUser.getRole());
String refreshToken = jwtTokenUtil.generateRefreshToken(targetUser.getId(), targetUser.getEmail());
redisTemplate.opsForValue().set(targetUser.getId().toString(), refreshToken, REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.SECONDS); // Redis에 저장 (key: userId, value: refreshToken)
redisTemplate.opsForValue().set(refreshToken, clientIp, REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.SECONDS); // Redis에 저장 (key: userId, value: refreshToken)

return LoginResponseDto.builder()
.accessToken(accessToken)
Expand Down

0 comments on commit 4e4d162

Please sign in to comment.