Skip to content

Commit eb62130

Browse files
authored
Merge pull request #135 from studio-recoding/feat-refresh-token
[🚀feat] refresh token 로직 구현
2 parents a4e845b + 010223d commit eb62130

17 files changed

+188
-81
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package Ness.Backend.domain.auth;
2+
3+
import Ness.Backend.domain.auth.dto.request.PostRefreshTokenDto;
4+
import Ness.Backend.domain.auth.dto.response.GetJwtTokenDto;
5+
import Ness.Backend.domain.member.entity.Member;
6+
import Ness.Backend.global.auth.AuthUser;
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.web.bind.annotation.PostMapping;
10+
import org.springframework.web.bind.annotation.RequestBody;
11+
import org.springframework.web.bind.annotation.RequestMapping;
12+
import org.springframework.web.bind.annotation.RestController;
13+
14+
@RestController
15+
@RequiredArgsConstructor
16+
@RequestMapping(value = "/auth")
17+
public class AuthController {
18+
private final AuthService authService;
19+
20+
@PostMapping("/logout")
21+
@Operation(summary = "로그아웃 요청", description = "로그아웃 요청 API 입니다.")
22+
public void logout(@AuthUser Member member, @RequestBody PostRefreshTokenDto postRefreshTokenDto) {
23+
authService.logout(member, postRefreshTokenDto);
24+
}
25+
26+
@PostMapping("/reIssuance")
27+
@Operation(summary = "JWT access 토큰 재발급 요청", description = "JWT access 토큰 재발급 요청 API 입니다.")
28+
public GetJwtTokenDto reIssuance(@AuthUser Member member, @RequestBody PostRefreshTokenDto postRefreshTokenDto) {
29+
return authService.reIssuance(member, postRefreshTokenDto);
30+
}
31+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package Ness.Backend.domain.auth;
2+
3+
import Ness.Backend.domain.auth.dto.request.PostRefreshTokenDto;
4+
import Ness.Backend.domain.auth.dto.response.GetJwtTokenDto;
5+
import Ness.Backend.domain.auth.inmemory.RefreshTokenRepository;
6+
import Ness.Backend.domain.auth.jwt.JwtTokenProvider;
7+
import Ness.Backend.domain.member.entity.Member;
8+
import Ness.Backend.global.error.ErrorCode;
9+
import Ness.Backend.global.error.exception.UnauthorizedException;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.security.core.context.SecurityContextHolder;
12+
import org.springframework.stereotype.Service;
13+
import org.springframework.transaction.annotation.Transactional;
14+
15+
import java.util.Date;
16+
17+
@Service
18+
@RequiredArgsConstructor
19+
public class AuthService {
20+
private final JwtTokenProvider jwtTokenProvider;
21+
private final RefreshTokenRepository refreshTokenRepository;
22+
23+
@Transactional
24+
public void logout(Member member, PostRefreshTokenDto postRefreshTokenDto) {
25+
/* refreshToken 만료 여부 확인 */
26+
if(refreshTokenRepository.findRefreshTokenByJwtRefreshToken(postRefreshTokenDto.getJwtRefreshToken()).isEmpty()){
27+
throw new UnauthorizedException(ErrorCode.INVALID_REFRESH_TOKEN);
28+
}
29+
30+
refreshTokenRepository.deleteRefreshTokenByJwtRefreshToken(postRefreshTokenDto.getJwtRefreshToken());
31+
SecurityContextHolder.clearContext();
32+
}
33+
34+
@Transactional
35+
public GetJwtTokenDto reIssuance(Member member, PostRefreshTokenDto postRefreshTokenDto) {
36+
/* refreshToken 유효성 확인 */
37+
if (!jwtTokenProvider.validRefreshToken(postRefreshTokenDto.getJwtRefreshToken())) {
38+
throw new UnauthorizedException(ErrorCode.INVALID_TOKEN);
39+
}
40+
41+
/* refreshToken 만료 여부 확인 */
42+
if(refreshTokenRepository.findRefreshTokenByJwtRefreshToken(postRefreshTokenDto.getJwtRefreshToken()).isEmpty()){
43+
throw new UnauthorizedException(ErrorCode.INVALID_REFRESH_TOKEN);
44+
}
45+
46+
final GetJwtTokenDto generateToken = GetJwtTokenDto.builder()
47+
.jwtAccessToken(jwtTokenProvider.generateAccessToken(member.getEmail(), new Date()))
48+
.jwtRefreshToken(postRefreshTokenDto.getJwtRefreshToken())
49+
.build();
50+
51+
return generateToken;
52+
}
53+
}

src/main/java/Ness/Backend/domain/auth/dto/LoginRequestDto.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/main/java/Ness/Backend/domain/auth/dto/RegisterRequestDto.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/main/java/Ness/Backend/domain/auth/dto/ResourceDto.java

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package Ness.Backend.domain.auth.dto.request;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
import lombok.Getter;
5+
import lombok.ToString;
6+
7+
@Getter
8+
@ToString
9+
public class PostRefreshTokenDto {
10+
@NotNull
11+
private String jwtRefreshToken;
12+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package Ness.Backend.domain.auth.dto.response;
2+
3+
4+
import lombok.Builder;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
import lombok.ToString;
8+
9+
@Getter
10+
@ToString
11+
@NoArgsConstructor
12+
public class GetJwtTokenDto {
13+
private String jwtAccessToken;
14+
private String jwtRefreshToken;
15+
16+
@Builder
17+
public GetJwtTokenDto(String jwtAccessToken, String jwtRefreshToken) {
18+
this.jwtAccessToken = jwtAccessToken;
19+
this.jwtRefreshToken = jwtRefreshToken;
20+
}
21+
}

src/main/java/Ness/Backend/domain/auth/inmemory/RefreshTokenRepository.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33
import Ness.Backend.domain.auth.inmemory.entity.RefreshToken;
44
import org.springframework.data.repository.CrudRepository;
55

6+
import java.util.Optional;
7+
68
public interface RefreshTokenRepository extends CrudRepository<RefreshToken, Long> {
9+
Optional<RefreshToken> findRefreshTokenByJwtRefreshToken(String refreshToken);
10+
11+
void deleteRefreshTokenByJwtRefreshToken(String refreshToken);
712
}

src/main/java/Ness/Backend/domain/auth/inmemory/RefreshTokenService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import org.springframework.stereotype.Service;
66
import org.springframework.transaction.annotation.Transactional;
77

8+
import java.util.Optional;
9+
810
@Service
911
@RequiredArgsConstructor
1012
@Transactional(readOnly = true)
@@ -19,4 +21,10 @@ public void saveRefreshToken(String refreshToken, String authKey) {
1921
.build();
2022
refreshTokenRepository.save(token);
2123
}
24+
25+
@Transactional
26+
public void removeRefreshToken(String refreshToken) {
27+
refreshTokenRepository.findRefreshTokenByJwtRefreshToken(refreshToken)
28+
.ifPresent(token -> refreshTokenRepository.delete(token));
29+
}
2230
}

src/main/java/Ness/Backend/domain/auth/inmemory/entity/RefreshToken.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@
1010

1111
@Getter
1212
@NoArgsConstructor
13-
@RedisHash(value = "refreshToken")
13+
@RedisHash(value = "refreshToken", timeToLive = 60*60*24*14)
1414
public class RefreshToken { /* Redis에 저장해서 RefreshToken이 유효한지 검증 */
1515
@Id
1616
@Indexed
1717
private String jwtRefreshToken;
1818

19+
// 맴버 이메일로 설정
1920
private String authKey;
2021

22+
//리프레시 토큰의 생명 주기(14일)
2123
@TimeToLive
2224
private Long ttl;
2325

0 commit comments

Comments
 (0)