Skip to content

Commit c2821f7

Browse files
authored
Merge pull request #8 from GSM-MSG/feature/7-reissue-token
๐Ÿ”€ ํ† ํฐ ์žฌ๋ฐœ๊ธ‰
2 parents e0457b8 + ebbcf15 commit c2821f7

File tree

9 files changed

+145
-1
lines changed

9 files changed

+145
-1
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.gcms.v3.domain.auth.domain.entity;
2+
3+
import lombok.Builder;
4+
import lombok.Getter;
5+
import org.springframework.data.annotation.Id;
6+
import org.springframework.data.redis.core.RedisHash;
7+
import org.springframework.data.redis.core.index.Indexed;
8+
9+
@Getter
10+
@Builder
11+
@RedisHash(value = "refreshToken", timeToLive = 60L * 60 * 24 * 7)
12+
public class RefreshToken {
13+
14+
@Indexed
15+
private String email;
16+
17+
@Id
18+
@Indexed
19+
private String token;
20+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.gcms.v3.domain.auth.domain.repository;
2+
3+
import com.gcms.v3.domain.auth.domain.entity.RefreshToken;
4+
import org.springframework.data.repository.CrudRepository;
5+
6+
import java.util.Optional;
7+
8+
public interface RefreshTokenRepository extends CrudRepository<RefreshToken, String> {
9+
Optional<RefreshToken> findByToken(String token);
10+
11+
RefreshToken findByEmail(String email);
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.gcms.v3.domain.auth.exception;
2+
3+
import com.gcms.v3.global.error.BasicException;
4+
import com.gcms.v3.global.error.ErrorCode;
5+
6+
public class ExpiredTokenException extends BasicException {
7+
public ExpiredTokenException() {
8+
super(ErrorCode.EXPIRED_TOKEN);
9+
}
10+
}

โ€Žsrc/main/java/com/gcms/v3/domain/auth/presentation/AuthController.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.gcms.v3.domain.auth.presentation.data.request.SignInRequestDto;
44
import com.gcms.v3.domain.auth.presentation.data.response.TokenInfoResponseDto;
5+
import com.gcms.v3.domain.auth.service.ReissueTokenService;
56
import com.gcms.v3.domain.auth.service.SignInService;
67
import lombok.RequiredArgsConstructor;
78
import org.springframework.http.ResponseEntity;
@@ -13,10 +14,17 @@
1314
public class AuthController {
1415

1516
private final SignInService signInService;
17+
private final ReissueTokenService reissueTokenService;
1618

1719
@PostMapping
1820
public ResponseEntity<TokenInfoResponseDto> signIn (@RequestBody SignInRequestDto signInRequestDto) {
1921
TokenInfoResponseDto res = signInService.execute(signInRequestDto);
2022
return ResponseEntity.ok(res);
2123
}
24+
25+
@PostMapping("/reissueToken")
26+
public ResponseEntity<TokenInfoResponseDto> reissueToken (@RequestBody String refreshToken) {
27+
TokenInfoResponseDto res = reissueTokenService.execute(refreshToken);
28+
return ResponseEntity.ok(res);
29+
}
2230
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.gcms.v3.domain.auth.service;
2+
3+
import com.gcms.v3.domain.auth.presentation.data.response.TokenInfoResponseDto;
4+
5+
public interface ReissueTokenService {
6+
TokenInfoResponseDto execute(String refreshToken);
7+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.gcms.v3.domain.auth.service.impl;
2+
3+
import com.gcms.v3.domain.auth.domain.entity.RefreshToken;
4+
import com.gcms.v3.domain.auth.domain.repository.RefreshTokenRepository;
5+
import com.gcms.v3.domain.auth.exception.UserNotFoundException;
6+
import com.gcms.v3.domain.auth.presentation.data.response.TokenInfoResponseDto;
7+
import com.gcms.v3.domain.auth.service.ReissueTokenService;
8+
import com.gcms.v3.domain.user.domain.entity.User;
9+
import com.gcms.v3.domain.user.domain.repository.UserRepository;
10+
import com.gcms.v3.global.security.exception.ExpiredTokenException;
11+
import com.gcms.v3.global.security.jwt.JwtTokenProvider;
12+
import lombok.RequiredArgsConstructor;
13+
import org.springframework.stereotype.Service;
14+
15+
@RequiredArgsConstructor
16+
@Service
17+
public class ReissueTokenServiceImpl implements ReissueTokenService {
18+
19+
private final JwtTokenProvider jwtTokenProvider;
20+
private final UserRepository userRepository;
21+
private final RefreshTokenRepository refreshTokenRepository;
22+
23+
public TokenInfoResponseDto execute(String refreshToken) {
24+
String refresh = jwtTokenProvider.parseToken(refreshToken);
25+
26+
String email = jwtTokenProvider.exactEmailFromRefreshToken(refresh);
27+
28+
User user = userRepository.findByEmail(email)
29+
.orElseThrow(UserNotFoundException::new);
30+
31+
RefreshToken existingRefreshToken = refreshTokenRepository.findByToken(refresh)
32+
.orElseThrow(ExpiredTokenException::new);
33+
34+
TokenInfoResponseDto responseDto = jwtTokenProvider.generateToken(user.getEmail());
35+
36+
saveRefreshToken(existingRefreshToken.getEmail(), responseDto.refreshToken());
37+
38+
return responseDto;
39+
}
40+
41+
private void saveRefreshToken(String email, String refreshToken) {
42+
RefreshToken token = RefreshToken.builder()
43+
.email(email)
44+
.token(refreshToken)
45+
.build();
46+
47+
refreshTokenRepository.save(token);
48+
}
49+
}

โ€Žsrc/main/java/com/gcms/v3/domain/auth/service/impl/SignInServiceImpl.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.gcms.v3.domain.auth.service.impl;
22

3+
import com.gcms.v3.domain.auth.domain.entity.RefreshToken;
4+
import com.gcms.v3.domain.auth.domain.repository.RefreshTokenRepository;
35
import com.gcms.v3.domain.auth.presentation.data.request.SignInRequestDto;
46
import com.gcms.v3.domain.auth.presentation.data.response.TokenInfoResponseDto;
57
import com.gcms.v3.domain.auth.service.SignInService;
@@ -24,6 +26,7 @@ public class SignInServiceImpl implements SignInService {
2426
private final UserRepository userRepository;
2527
private final JwtTokenProvider jwtTokenProvider;
2628
private final UserRoleRepository userRoleRepository;
29+
private final RefreshTokenRepository refreshTokenRepository;
2730

2831
public TokenInfoResponseDto execute(SignInRequestDto signInRequestDto) {
2932
String accessToken = oAuth2Service.requestAccessToken(signInRequestDto.code());
@@ -32,7 +35,11 @@ public TokenInfoResponseDto execute(SignInRequestDto signInRequestDto) {
3235
User user = userRepository.findByEmail(googleOAuth2UserInfo.getEmail())
3336
.orElseGet(() -> toEntity(googleOAuth2UserInfo));
3437

35-
return jwtTokenProvider.generateToken(user.getEmail());
38+
TokenInfoResponseDto responseDto = jwtTokenProvider.generateToken(user.getEmail());
39+
40+
saveRefreshToken(user.getEmail(), responseDto.refreshToken());
41+
42+
return responseDto;
3643
}
3744

3845
private User toEntity(GoogleOAuth2UserInfo googleOAuth2UserInfo) {
@@ -55,4 +62,12 @@ private void saveAuthority(User user) {
5562
userRoleRepository.save(userRole);
5663
}
5764

65+
private void saveRefreshToken(String email, String refreshToken) {
66+
RefreshToken token = RefreshToken.builder()
67+
.email(email)
68+
.token(refreshToken)
69+
.build();
70+
71+
refreshTokenRepository.save(token);
72+
}
5873
}

โ€Žsrc/main/java/com/gcms/v3/global/security/config/SecurityConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
4343
.authorizeHttpRequests((authorizeRequests) ->
4444
authorizeRequests
4545
.requestMatchers(HttpMethod.POST, "/v3/auth").permitAll()
46+
.requestMatchers(HttpMethod.POST, "/v3/auth/reissueToken").authenticated()
4647
)
4748

4849
.addFilterBefore(new ExceptionFilter(objectMapper), UsernamePasswordAuthenticationFilter.class)

โ€Žsrc/main/java/com/gcms/v3/global/security/jwt/JwtTokenProvider.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,26 @@ public boolean validateToken(String token) {
126126
}
127127
}
128128

129+
public String parseToken(String token) {
130+
if (token.startsWith(TOKEN_PREFIX)) {
131+
return token.replace(TOKEN_PREFIX, "");
132+
}
133+
else return null;
134+
}
135+
136+
public String exactEmailFromRefreshToken(String refreshToken) {
137+
return getTokenSubject(refreshToken, refreshtokenkey);
138+
}
139+
140+
private String getTokenSubject (String token, Key secret) {
141+
return getTokenBody(token, secret).getSubject();
142+
}
143+
144+
private Claims getTokenBody(String token, Key secret) {
145+
return Jwts.parserBuilder()
146+
.setSigningKey(secret)
147+
.build()
148+
.parseClaimsJws(token)
149+
.getBody();
150+
}
129151
}

0 commit comments

Comments
ย (0)