From d23125e7480f2bf79bbbfe543171d97c16d00bb0 Mon Sep 17 00:00:00 2001 From: JaeSeo Yang <96044622+psychology50@users.noreply.github.com> Date: Sun, 24 Dec 2023 21:53:42 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20#11=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EC=A0=84=ED=99=94=EB=B2=88=ED=98=B8=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=84=B1=EA=B3=B5=20=EC=8B=9C,=20oauth=20=EA=B3=84?= =?UTF-8?q?=EC=A0=95=20=EC=A1=B4=EC=9E=AC=ED=95=98=EB=A9=B4=20=EB=B0=94?= =?UTF-8?q?=EB=A1=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B3=BC=EC=A0=95=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fitapet/domain/member/api/AuthApi.java | 28 +++++++++------ .../fitapet/domain/member/domain/Member.java | 6 +++- .../service/component/MemberAuthService.java | 34 +++++++++++++------ .../global/common/security/jwt/dto/Jwt.java | 6 ++++ 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/kcy/fitapet/domain/member/api/AuthApi.java b/src/main/java/com/kcy/fitapet/domain/member/api/AuthApi.java index 9e6ff960..8becdb39 100644 --- a/src/main/java/com/kcy/fitapet/domain/member/api/AuthApi.java +++ b/src/main/java/com/kcy/fitapet/domain/member/api/AuthApi.java @@ -3,6 +3,7 @@ import com.kcy.fitapet.domain.member.dto.auth.SignInReq; import com.kcy.fitapet.domain.member.dto.auth.SignUpReq; import com.kcy.fitapet.global.common.redis.sms.type.SmsPrefix; +import com.kcy.fitapet.global.common.security.jwt.dto.Jwt; import com.kcy.fitapet.global.common.util.sms.dto.SmsReq; import com.kcy.fitapet.global.common.util.sms.dto.SmsRes; import com.kcy.fitapet.domain.member.exception.SmsErrorCode; @@ -67,7 +68,7 @@ public class AuthApi { @PostMapping("/register") @PreAuthorize("isAnonymous()") public ResponseEntity signUp(@RequestHeader("Authorization") @NotBlank String accessToken, @RequestBody @Valid SignUpReq dto) { - Map tokens = memberAuthService.register(accessToken, dto); + Jwt tokens = memberAuthService.register(accessToken, dto); return getResponseEntity(tokens); } @@ -91,13 +92,20 @@ public ResponseEntity registerSmsAuthorization( return ResponseEntity.ok(SuccessResponse.from(smsRes)); } - String token = memberAuthService.checkCodeForRegister(dto, code); - if (!StringUtils.hasText(token)) + Jwt token = memberAuthService.checkCodeForRegister(dto, code); + if (token == null) throw new GlobalErrorException(SmsErrorCode.INVALID_AUTH_CODE); + else if (token.refreshToken() == null) + return ResponseEntity.ok() + .header(ACCESS_TOKEN.getValue(), token.accessToken()) + .body(SuccessResponse.noContent()); + + ResponseCookie cookie = cookieUtil.createCookie(REFRESH_TOKEN.getValue(), token.refreshToken(), 60 * 60 * 24 * 7); return ResponseEntity.ok() - .header(ACCESS_TOKEN.getValue(), token) - .body(SuccessResponse.noContent()); + .header(HttpHeaders.SET_COOKIE, cookie.toString()) + .header(ACCESS_TOKEN.getValue(), token.accessToken()) + .body(SuccessResponse.from(Map.of("member", "등록된 oauth 계정 연동 성공"))); } @Operation(summary = "ID/PW 찾기 전화번호 인증") @@ -139,7 +147,7 @@ public ResponseEntity searchSmsAuthorization( public ResponseEntity signIn(@RequestHeader(value = "Authorization", required = false) String accessToken, @RequestBody @Valid SignInReq dto) { if (accessToken != null) throw new GlobalErrorException(ErrorCode.ALREADY_LOGIN_USER); - Map tokens = memberAuthService.login(dto); + Jwt tokens = memberAuthService.login(dto); return getResponseEntity(tokens); } @@ -184,7 +192,7 @@ public ResponseEntity signOut( }) @GetMapping("/refresh") public ResponseEntity refresh(@CookieValue("refreshToken") @Valid String refreshToken) { - Map tokens = memberAuthService.refresh(refreshToken); + Jwt tokens = memberAuthService.refresh(refreshToken); return getResponseEntity(tokens); } @@ -193,12 +201,12 @@ public ResponseEntity refresh(@CookieValue("refreshToken") @Valid String refr * @param tokens : 액세스 토큰과 리프레시 토큰 * @return ResponseEntity */ - private ResponseEntity getResponseEntity(Map tokens) { - ResponseCookie cookie = cookieUtil.createCookie(REFRESH_TOKEN.getValue(), tokens.get(REFRESH_TOKEN.getValue()), 60 * 60 * 24 * 7); + private ResponseEntity getResponseEntity(Jwt tokens) { + ResponseCookie cookie = cookieUtil.createCookie(REFRESH_TOKEN.getValue(), tokens.refreshToken(), 60 * 60 * 24 * 7); return ResponseEntity.ok() .header(HttpHeaders.SET_COOKIE, cookie.toString()) - .header(ACCESS_TOKEN.getValue(), tokens.get(ACCESS_TOKEN.getValue())) + .header(ACCESS_TOKEN.getValue(), tokens.accessToken()) .body(SuccessResponse.noContent()); } } diff --git a/src/main/java/com/kcy/fitapet/domain/member/domain/Member.java b/src/main/java/com/kcy/fitapet/domain/member/domain/Member.java index 4b3c57ba..ee8b547b 100644 --- a/src/main/java/com/kcy/fitapet/domain/member/domain/Member.java +++ b/src/main/java/com/kcy/fitapet/domain/member/domain/Member.java @@ -38,7 +38,7 @@ public class Member extends Auditable { private String profileImg; @Column(name = "account_locked") @ColumnDefault("false") private Boolean accountLocked; - @Column(name = "is_oauth") @ColumnDefault("false") + @Column(name = "is_oauth") @ColumnDefault("false") @Getter private Boolean isOauth; @Convert(converter = RoleTypeConverter.class) @Getter @@ -120,4 +120,8 @@ public void updatePassword(String password, PasswordEncoder passwordEncoder) { public void updateNotificationFromType(NotificationType type) { this.notificationSetting.updateNotificationFromType(type); } + + public void updateOathToOriginAccount() { + this.isOauth = Boolean.FALSE; + } } diff --git a/src/main/java/com/kcy/fitapet/domain/member/service/component/MemberAuthService.java b/src/main/java/com/kcy/fitapet/domain/member/service/component/MemberAuthService.java index ff03e31d..585f8c98 100644 --- a/src/main/java/com/kcy/fitapet/domain/member/service/component/MemberAuthService.java +++ b/src/main/java/com/kcy/fitapet/domain/member/service/component/MemberAuthService.java @@ -7,11 +7,13 @@ import com.kcy.fitapet.domain.member.exception.SmsErrorCode; import com.kcy.fitapet.domain.member.service.module.MemberSaveService; import com.kcy.fitapet.domain.member.service.module.MemberSearchService; +import com.kcy.fitapet.domain.oauth.service.module.OauthSearchService; import com.kcy.fitapet.global.common.redis.sms.SmsRedisHelper; import com.kcy.fitapet.global.common.resolver.access.AccessToken; import com.kcy.fitapet.global.common.response.code.StatusCode; import com.kcy.fitapet.global.common.response.exception.GlobalErrorException; import com.kcy.fitapet.global.common.security.jwt.JwtUtil; +import com.kcy.fitapet.global.common.security.jwt.dto.Jwt; import com.kcy.fitapet.global.common.security.jwt.dto.JwtUserInfo; import com.kcy.fitapet.global.common.security.jwt.dto.SmsAuthInfo; import com.kcy.fitapet.global.common.redis.forbidden.ForbiddenTokenService; @@ -42,6 +44,7 @@ public class MemberAuthService { private final MemberSearchService memberSearchService; private final MemberSaveService memberSaveService; + private final OauthSearchService oauthSearchService; private final RefreshTokenService refreshTokenService; private final ForbiddenTokenService forbiddenTokenService; @@ -54,7 +57,7 @@ public class MemberAuthService { private final PasswordEncoder bCryptPasswordEncoder; @Transactional - public Map register(String requestAccessToken, SignUpReq dto) { + public Jwt register(String requestAccessToken, SignUpReq dto) { String accessToken = jwtUtil.resolveToken(requestAccessToken); if (forbiddenTokenService.isForbidden(accessToken)) throw new GlobalErrorException(AuthErrorCode.FORBIDDEN_ACCESS_TOKEN); @@ -76,7 +79,7 @@ public Map register(String requestAccessToken, SignUpReq dto) { } @Transactional - public Map login(SignInReq dto) { + public Jwt login(SignInReq dto) { Member member = memberSearchService.findByUid(dto.uid()); if (!member.checkPassword(dto.password(), bCryptPasswordEncoder)) throw new GlobalErrorException(AccountErrorCode.NOT_MATCH_PASSWORD_ERROR); @@ -93,14 +96,14 @@ public void logout(AccessToken requestAccessToken, String requestRefreshToken) { } @Transactional - public Map refresh(String requestRefreshToken) { + public Jwt refresh(String requestRefreshToken) { RefreshToken refreshToken = refreshTokenService.refresh(requestRefreshToken); Long memberId = refreshToken.getUserId(); JwtUserInfo dto = JwtUserInfo.from(memberSearchService.findById(memberId)); String accessToken = jwtUtil.generateAccessToken(dto); - return Map.of(ACCESS_TOKEN.getValue(), accessToken, REFRESH_TOKEN.getValue(), refreshToken.getToken()); + return Jwt.of(accessToken, refreshToken.getToken()); } @Transactional @@ -115,13 +118,22 @@ public SmsRes sendCode(SmsReq dto, SmsPrefix prefix) { } @Transactional - public String checkCodeForRegister(SmsReq smsReq, String requestCode) { + public Jwt checkCodeForRegister(SmsReq smsReq, String requestCode) { if (!smsRedisHelper.isCorrectCode(smsReq.to(), requestCode, SmsPrefix.REGISTER)) { log.warn("인증번호 불일치 -> 사용자 입력 인증 번호 : {}", requestCode); throw new GlobalErrorException(SmsErrorCode.INVALID_AUTH_CODE); } smsRedisHelper.removeCode(smsReq.to(), SmsPrefix.REGISTER); - return jwtUtil.generateSmsAuthToken(SmsAuthInfo.of(1L, smsReq.to())); + + if (memberSearchService.isExistByPhone(smsReq.to())) { + Member member = memberSearchService.findByPhone(smsReq.to()); + if (member.getIsOauth().equals(Boolean.TRUE)) { + member.updateOathToOriginAccount(); + return generateToken(JwtUserInfo.from(member)); + } + } + + return Jwt.of(jwtUtil.generateSmsAuthToken(SmsAuthInfo.of(1L, smsReq.to())), null); } @Transactional(readOnly = true) @@ -142,8 +154,10 @@ public void checkCodeForSearch(SmsReq req, String code, SmsPrefix prefix) { private void validateForSms(SmsPrefix prefix, SmsReq req) { boolean isExistPhone = memberSearchService.isExistByPhone(req.to()); if (prefix.equals(SmsPrefix.REGISTER) && isExistPhone) { - log.warn("중복된 전화번호로 인한 회원가입 요청 실패: {}", req.to()); - throw new GlobalErrorException(AccountErrorCode.DUPLICATE_PHONE_ERROR); + if (!memberSearchService.findByPhone(req.to()).getIsOauth()) { + log.warn("중복된 전화번호로 인한 회원가입 요청 실패: {}", req.to()); + throw new GlobalErrorException(AccountErrorCode.DUPLICATE_PHONE_ERROR); + } } else if (prefix.equals(SmsPrefix.UID) && !isExistPhone) { log.warn("DB에 존재하지 않는 전화번호로 인한 SMS 인증 요청 실패: {}", req.to()); throw new GlobalErrorException(AccountErrorCode.NOT_FOUND_PHONE_ERROR); @@ -163,11 +177,11 @@ private void validateMember(Member member) { throw new GlobalErrorException(AccountErrorCode.DUPLICATE_USER_INFO_ERROR); } - private Map generateToken(JwtUserInfo jwtUserInfo) { + private Jwt generateToken(JwtUserInfo jwtUserInfo) { String accessToken = jwtUtil.generateAccessToken(jwtUserInfo); String refreshToken = refreshTokenService.issueRefreshToken(accessToken); log.debug("accessToken : {}, refreshToken : {}", accessToken, refreshToken); - return Map.of(ACCESS_TOKEN.getValue(), accessToken, REFRESH_TOKEN.getValue(), refreshToken); + return Jwt.of(accessToken, refreshToken); } } diff --git a/src/main/java/com/kcy/fitapet/global/common/security/jwt/dto/Jwt.java b/src/main/java/com/kcy/fitapet/global/common/security/jwt/dto/Jwt.java index a5b228df..0ae1856b 100644 --- a/src/main/java/com/kcy/fitapet/global/common/security/jwt/dto/Jwt.java +++ b/src/main/java/com/kcy/fitapet/global/common/security/jwt/dto/Jwt.java @@ -7,4 +7,10 @@ public record Jwt( String accessToken, String refreshToken ) { + public static Jwt of(String accessToken, String refreshToken) { + return Jwt.builder() + .accessToken(accessToken) + .refreshToken(refreshToken) + .build(); + } }