Skip to content

Commit 93e7379

Browse files
authored
Merge pull request #9 from WhosInRoom/feat/#5-mail-validation
[Feat] 메일 인증 구현
2 parents e7e347c + ee24644 commit 93e7379

16 files changed

Lines changed: 385 additions & 43 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ out/
3535

3636
### VS Code ###
3737
.vscode/
38+
39+
### .env file ###
40+
*.env
41+
Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
package com.WhoIsRoom.WhoIs_Server.domain.auth.controller;
22

3+
import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.CodeCheckRequest;
4+
import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.MailRequest;
5+
import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.PasswordRequest;
6+
import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.RefreshTokenRequest;
7+
import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.response.ReissueResponse;
38
import com.WhoIsRoom.WhoIs_Server.domain.auth.service.JwtService;
9+
import com.WhoIsRoom.WhoIs_Server.domain.auth.service.MailService;
10+
import com.WhoIsRoom.WhoIs_Server.domain.user.service.UserService;
11+
import com.WhoIsRoom.WhoIs_Server.global.common.resolver.CurrentUserId;
412
import com.WhoIsRoom.WhoIs_Server.global.common.response.BaseResponse;
513
import jakarta.servlet.http.HttpServletRequest;
6-
import jakarta.servlet.http.HttpServletResponse;
714
import lombok.RequiredArgsConstructor;
815
import lombok.extern.slf4j.Slf4j;
9-
import org.springframework.web.bind.annotation.PostMapping;
10-
import org.springframework.web.bind.annotation.RequestMapping;
11-
import org.springframework.web.bind.annotation.RequestParam;
12-
import org.springframework.web.bind.annotation.RestController;
16+
import org.springframework.web.bind.annotation.*;
1317

1418
@Slf4j
1519
@RestController
@@ -18,16 +22,44 @@
1822
public class AuthController {
1923

2024
private final JwtService jwtService;
25+
private final MailService mailService;
26+
private final UserService userService;
2127

2228
@PostMapping("/logout")
23-
public BaseResponse<Void> logout(HttpServletRequest request){
24-
jwtService.logout(request);
29+
public BaseResponse<Void> logout(HttpServletRequest request,
30+
@RequestBody RefreshTokenRequest tokenRequest){
31+
jwtService.logout(request, tokenRequest);
2532
return BaseResponse.ok(null);
2633
}
2734

2835
@PostMapping("/reissue")
29-
public BaseResponse<Void> reissueTokens(HttpServletRequest request, HttpServletResponse response) {
30-
jwtService.reissueTokens(request, response);
36+
public BaseResponse<ReissueResponse> reissueTokens(@RequestBody RefreshTokenRequest tokenRequest) {
37+
ReissueResponse response = jwtService.reissueTokens(tokenRequest);
38+
return BaseResponse.ok(response);
39+
}
40+
41+
@PostMapping("/email/send")
42+
public BaseResponse<Void> sendAuthCodeMail(@RequestBody MailRequest request) {
43+
mailService.sendMail(request);
44+
return BaseResponse.ok(null);
45+
}
46+
47+
@PostMapping("/email/validation")
48+
public BaseResponse<Void> checkAuthCode(@RequestBody CodeCheckRequest request) {
49+
mailService.checkAuthCode(request);
50+
return BaseResponse.ok(null);
51+
}
52+
53+
@PostMapping("/email/find-password")
54+
public BaseResponse<Void> findPassword(@RequestBody MailRequest request) {
55+
userService.sendNewPassword(request);
56+
return BaseResponse.ok(null);
57+
}
58+
59+
@PatchMapping("/password")
60+
public BaseResponse<Void> updatePassword(@CurrentUserId Long userId,
61+
@RequestBody PasswordRequest request) {
62+
userService.updateMyPassword(userId, request);
3163
return BaseResponse.ok(null);
3264
}
3365
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.NotNull;
5+
import lombok.AccessLevel;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
9+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
10+
@Getter
11+
public class CodeCheckRequest {
12+
private String email;
13+
private String authCode;
14+
}
15+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.NotNull;
5+
import lombok.AccessLevel;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
9+
@Getter
10+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
11+
public class MailRequest {
12+
private String email;
13+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request;
2+
3+
import lombok.AccessLevel;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
7+
@Getter
8+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
9+
public class PasswordRequest {
10+
private String prePassword;
11+
private String newPassword;
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request;
2+
3+
import lombok.AccessLevel;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
7+
@Getter
8+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
9+
public class RefreshTokenRequest {
10+
private String refreshToken;
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.WhoIsRoom.WhoIs_Server.domain.auth.dto.response;
2+
3+
import lombok.Builder;
4+
import lombok.Getter;
5+
6+
@Getter
7+
@Builder
8+
public class ReissueResponse {
9+
private String accessToken;
10+
private String refreshToken;
11+
}

src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/handler/success/CustomAuthenticationSuccessHandler.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
4747
jwtService.storeRefreshToken(refreshToken);
4848
log.info("[CustomAuthenticationSuccessHandler], refreshToken={}", refreshToken);
4949

50-
jwtService.sendTokens(response, accessToken, refreshToken);
51-
5250
LoginResponse data = LoginResponse.builder()
5351
.accessToken(accessToken)
5452
.refreshToken(refreshToken)

src/main/java/com/WhoIsRoom/WhoIs_Server/domain/auth/service/JwtService.java

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
package com.WhoIsRoom.WhoIs_Server.domain.auth.service;
22

3+
import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.request.RefreshTokenRequest;
4+
import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.response.LoginResponse;
5+
import com.WhoIsRoom.WhoIs_Server.domain.auth.dto.response.ReissueResponse;
36
import com.WhoIsRoom.WhoIs_Server.domain.auth.exception.CustomAuthenticationException;
47
import com.WhoIsRoom.WhoIs_Server.domain.auth.exception.CustomJwtException;
58
import com.WhoIsRoom.WhoIs_Server.domain.auth.util.JwtUtil;
69
import com.WhoIsRoom.WhoIs_Server.global.common.redis.RedisService;
10+
import com.WhoIsRoom.WhoIs_Server.global.common.response.BaseResponse;
711
import com.WhoIsRoom.WhoIs_Server.global.common.response.ErrorCode;
12+
import com.fasterxml.jackson.databind.ObjectMapper;
813
import jakarta.servlet.http.HttpServletRequest;
914
import jakarta.servlet.http.HttpServletResponse;
1015
import lombok.RequiredArgsConstructor;
1116
import lombok.extern.slf4j.Slf4j;
1217
import org.springframework.beans.factory.annotation.Value;
18+
import org.springframework.http.MediaType;
1319
import org.springframework.stereotype.Service;
1420

21+
import java.io.IOException;
1522
import java.time.Duration;
1623

1724
@Slf4j
@@ -37,27 +44,30 @@ public class JwtService {
3744

3845
private final RedisService redisService;
3946
private final JwtUtil jwtUtil;
47+
private final ObjectMapper objectMapper;
4048

41-
public void logout(HttpServletRequest request) {
49+
public void logout(HttpServletRequest request, RefreshTokenRequest tokenRequest) {
4250
String accessToken = jwtUtil.extractAccessToken(request)
4351
.orElseThrow(() -> new CustomAuthenticationException(ErrorCode.SECURITY_INVALID_ACCESS_TOKEN));
44-
String refreshToken = jwtUtil.extractRefreshToken(request)
45-
.orElseThrow(() -> new CustomAuthenticationException(ErrorCode.SECURITY_INVALID_REFRESH_TOKEN));
52+
53+
String refreshToken = tokenRequest.getRefreshToken();
54+
jwtUtil.validateToken(refreshToken);
55+
if (!"refresh".equals(jwtUtil.getTokenType(refreshToken))) {
56+
throw new CustomJwtException(ErrorCode.INVALID_TOKEN_TYPE);
57+
}
4658

4759
deleteRefreshToken(refreshToken);
4860
//access token blacklist 처리 -> 로그아웃한 사용자가 요청 시 access token이 redis에 존재하면 jwtAuthenticationFilter에서 인증처리 거부
4961
invalidAccessToken(accessToken);
5062
}
5163

52-
public void reissueTokens(HttpServletRequest request, HttpServletResponse response) {
53-
String refreshToken = jwtUtil.extractRefreshToken(request)
54-
.orElseThrow(() -> new CustomAuthenticationException(ErrorCode.SECURITY_INVALID_REFRESH_TOKEN));
55-
64+
public ReissueResponse reissueTokens(RefreshTokenRequest tokenRequest) {
65+
String refreshToken = tokenRequest.getRefreshToken();
5666
jwtUtil.validateToken(refreshToken);
5767
if (!"refresh".equals(jwtUtil.getTokenType(refreshToken))) {
5868
throw new CustomJwtException(ErrorCode.INVALID_TOKEN_TYPE);
5969
}
60-
reissueAndSendTokens(response, refreshToken);
70+
return reissueAndSendTokens(refreshToken);
6171
}
6272

6373
public void checkLogout(String accessToken) {
@@ -83,7 +93,7 @@ private void invalidAccessToken(String accessToken) {
8393
Duration.ofMillis(ACCESS_TOKEN_EXPIRED_IN));
8494
}
8595

86-
private void reissueAndSendTokens(HttpServletResponse response, String refreshToken) {
96+
private ReissueResponse reissueAndSendTokens(String refreshToken) {
8797

8898
// 새로운 Refresh Token 발급
8999
String reissuedAccessToken = jwtUtil.createAccessToken(jwtUtil.getUserId(refreshToken), jwtUtil.getProviderId(refreshToken), jwtUtil.getRole(refreshToken), jwtUtil.getName(refreshToken));
@@ -95,12 +105,9 @@ private void reissueAndSendTokens(HttpServletResponse response, String refreshTo
95105
// 기존 Refresh Token 폐기 (DB나 Redis에서 삭제)
96106
deleteRefreshToken(refreshToken);
97107

98-
sendTokens(response, reissuedAccessToken, reissuedRefreshToken);
99-
}
100-
101-
public void sendTokens(HttpServletResponse response, String accessToken,
102-
String refreshToken) {
103-
response.setHeader(ACCESS_HEADER, BEARER_PREFIX + accessToken);
104-
response.setHeader(REFRESH_HEADER, BEARER_PREFIX + refreshToken);
108+
return ReissueResponse.builder()
109+
.accessToken(reissuedAccessToken)
110+
.refreshToken(reissuedRefreshToken)
111+
.build();
105112
}
106113
}

0 commit comments

Comments
 (0)