Skip to content

Commit

Permalink
Merge pull request #67 from kduoh99/refactor/#66
Browse files Browse the repository at this point in the history
Refactor: refreshToken 관리 리팩토링
  • Loading branch information
kduoh99 authored Aug 12, 2024
2 parents ad4f8b2 + 4bb5d55 commit 3868491
Show file tree
Hide file tree
Showing 17 changed files with 190 additions and 166 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ dependencies {

// iamport
implementation 'com.github.iamport:iamport-rest-client-java:0.1.6'

// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}

// iamport
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.skhu.moodfriend.app.controller.auth;

import com.skhu.moodfriend.app.dto.auth.reqDto.LoginReqDto;
import com.skhu.moodfriend.app.dto.auth.reqDto.RefreshTokenReqDto;
import com.skhu.moodfriend.app.dto.auth.reqDto.SignUpReqDto;
import com.skhu.moodfriend.app.dto.auth.resDto.AuthResDto;
import com.skhu.moodfriend.app.service.auth.GoogleOAuthService;
import com.skhu.moodfriend.app.service.auth.KakaoOAuthService;
import com.skhu.moodfriend.app.service.auth.LoginService;
import com.skhu.moodfriend.app.service.auth.SignUpService;
import com.skhu.moodfriend.app.service.auth.*;
import com.skhu.moodfriend.global.template.ApiResponseTemplate;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand All @@ -27,6 +25,7 @@ public class AuthController {
private final LoginService loginService;
private final GoogleOAuthService googleOauthService;
private final KakaoOAuthService kakaoOAuthService;
private final TokenRenewService tokenRenewService;

@PostMapping("/signUp")
@Operation(
Expand Down Expand Up @@ -89,4 +88,19 @@ public ResponseEntity<ApiResponseTemplate<AuthResDto>> kakaoCallback(@RequestPar
ApiResponseTemplate<AuthResDto> data = kakaoOAuthService.signUpOrLogin(kakaoOAuthService.getKakaoAccessToken(code).getData());
return ResponseEntity.status(data.getStatus()).body(data);
}

@PostMapping("/renew")
@Operation(
summary = "accessToken 재발급",
description = "refreshToken을 사용하여 새로운 accessToken을 발급합니다.",
responses = {
@ApiResponse(responseCode = "200", description = "토큰 재발급 성공"),
@ApiResponse(responseCode = "400", description = "잘못된 요청"),
@ApiResponse(responseCode = "500", description = "관리자 문의")
}
)
public ResponseEntity<ApiResponseTemplate<AuthResDto>> renewAccessToken(@RequestBody RefreshTokenReqDto refreshTokenReqDto) {
ApiResponseTemplate<AuthResDto> data = tokenRenewService.renewAccessToken(refreshTokenReqDto.refreshToken());
return ResponseEntity.status(data.getStatus()).body(data);
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.skhu.moodfriend.app.dto.auth.reqDto;

import lombok.Builder;

@Builder
public record RefreshTokenReqDto(
String refreshToken
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ public record AuthResDto(
String accessToken,
String refreshToken
) {
public static AuthResDto of(String accessToken, String refreshToken) {
return AuthResDto.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static MemberInfoResDto of(Member member) {
return MemberInfoResDto.builder()
.email(member.getEmail())
.name(member.getName())
.mileage(member.getMileage())
.mileage(member.getMileage() != null ? member.getMileage() : 0)
.loginType(member.getLoginType().getDisplayName())
.build();
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.skhu.moodfriend.app.service.auth;

import com.google.gson.Gson;
import com.skhu.moodfriend.app.domain.member.RoleType;
import com.skhu.moodfriend.app.dto.auth.resDto.AuthResDto;
import com.skhu.moodfriend.app.domain.member.LoginType;
import com.skhu.moodfriend.app.domain.member.Member;
import com.skhu.moodfriend.app.domain.member.MemberRefreshToken;
import com.skhu.moodfriend.app.domain.member.RoleType;
import com.skhu.moodfriend.app.repository.MemberRefreshTokenRepository;
import com.skhu.moodfriend.app.repository.MemberRepository;
import com.skhu.moodfriend.global.dto.MemberInfo;
import com.skhu.moodfriend.global.dto.Token;
Expand Down Expand Up @@ -39,10 +37,12 @@ public class GoogleOAuthService {
@Value("${oauth.google.redirect-uri}")
private String GOOGLE_REDIRECT_URI;

private final String GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
@Value("${oauth.google.token-url}")
private String GOOGLE_TOKEN_URL;

private final MemberRepository memberRepository;
private final MemberRefreshTokenRepository memberRefreshTokenRepository;
private final TokenProvider tokenProvider;
private final TokenRenewService tokenRenewService;

public ApiResponseTemplate<String> getGoogleAccessToken(String code) {
RestTemplate restTemplate = new RestTemplate();
Expand Down Expand Up @@ -84,17 +84,8 @@ public ApiResponseTemplate<AuthResDto> signUpOrLogin(String googleAccessToken) {
String accessToken = tokenProvider.createAccessToken(member);
String refreshToken = tokenProvider.createRefreshToken(member);

MemberRefreshToken memberRefreshToken = new MemberRefreshToken();
memberRefreshToken.setRefreshToken(refreshToken);
memberRefreshToken.setMember(member);

memberRefreshTokenRepository.deleteByMember(member);
memberRefreshTokenRepository.save(memberRefreshToken);

AuthResDto resDto = AuthResDto.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.build();
tokenRenewService.saveRefreshToken(refreshToken, member.getMemberId());
AuthResDto resDto = AuthResDto.of(accessToken, refreshToken);

return ApiResponseTemplate.success(SuccessCode.LOGIN_MEMBER_SUCCESS, resDto);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.skhu.moodfriend.app.domain.member.RoleType;
import com.skhu.moodfriend.app.dto.auth.resDto.AuthResDto;
import com.skhu.moodfriend.app.domain.member.LoginType;
import com.skhu.moodfriend.app.domain.member.Member;
import com.skhu.moodfriend.app.domain.member.MemberRefreshToken;
import com.skhu.moodfriend.app.domain.member.RoleType;
import com.skhu.moodfriend.app.repository.MemberRefreshTokenRepository;
import com.skhu.moodfriend.app.repository.MemberRepository;
import com.skhu.moodfriend.global.dto.MemberInfo;
import com.skhu.moodfriend.global.dto.Token;
Expand Down Expand Up @@ -37,11 +35,12 @@ public class KakaoOAuthService {
@Value("${oauth.kakao.redirect-uri}")
private String KAKAO_REDIRECT_URI;

private final String KAKAO_TOKEN_URL = "https://kauth.kakao.com/oauth/token";
@Value("${oauth.kakao.token-url}")
private String KAKAO_TOKEN_URL;

private final MemberRepository memberRepository;
private final MemberRefreshTokenRepository memberRefreshTokenRepository;
private final TokenProvider tokenProvider;
private final TokenRenewService tokenRenewService;

public ApiResponseTemplate<String> getKakaoAccessToken(String code) {
RestTemplate restTemplate = new RestTemplate();
Expand Down Expand Up @@ -87,17 +86,8 @@ public ApiResponseTemplate<AuthResDto> signUpOrLogin(String kakaoAccessToken) {
String accessToken = tokenProvider.createAccessToken(member);
String refreshToken = tokenProvider.createRefreshToken(member);

MemberRefreshToken memberRefreshToken = new MemberRefreshToken();
memberRefreshToken.setRefreshToken(refreshToken);
memberRefreshToken.setMember(member);

memberRefreshTokenRepository.deleteByMember(member);
memberRefreshTokenRepository.save(memberRefreshToken);

AuthResDto resDto = AuthResDto.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.build();
tokenRenewService.saveRefreshToken(refreshToken, member.getMemberId());
AuthResDto resDto = AuthResDto.of(accessToken, refreshToken);

return ApiResponseTemplate.success(SuccessCode.LOGIN_MEMBER_SUCCESS, resDto);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.skhu.moodfriend.app.service.auth;

import com.skhu.moodfriend.app.dto.auth.RenewAccessTokenDto;
import com.skhu.moodfriend.app.dto.auth.reqDto.LoginReqDto;
import com.skhu.moodfriend.app.domain.member.Member;
import com.skhu.moodfriend.app.domain.member.MemberRefreshToken;
import com.skhu.moodfriend.app.dto.auth.resDto.AuthResDto;
import com.skhu.moodfriend.app.repository.MemberRefreshTokenRepository;
import com.skhu.moodfriend.app.domain.member.Member;
import com.skhu.moodfriend.app.repository.MemberRepository;
import com.skhu.moodfriend.global.exception.CustomException;
import com.skhu.moodfriend.global.exception.code.ErrorCode;
Expand All @@ -23,15 +20,12 @@
public class LoginService {

private final MemberRepository memberRepository;
private final MemberRefreshTokenRepository memberRefreshTokenRepository;

private final PasswordEncoder passwordEncoder;
private final TokenProvider tokenProvider;
private final TokenRenewService tokenRenewService;
private final PasswordEncoder passwordEncoder;

@Transactional
public ApiResponseTemplate<AuthResDto> login(LoginReqDto loginReqDto) {

Member member = memberRepository.findByEmail(loginReqDto.email())
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_EMAIL_EXCEPTION,
ErrorCode.NOT_FOUND_EMAIL_EXCEPTION.getMessage()));
Expand All @@ -41,27 +35,15 @@ public ApiResponseTemplate<AuthResDto> login(LoginReqDto loginReqDto) {
ErrorCode.PASSWORD_MISMATCH_EXCEPTION.getMessage());
}

String renewRefreshToken = tokenProvider.createRefreshToken(member);

MemberRefreshToken refreshTokenEntity = memberRefreshTokenRepository.findByMember_MemberId(member.getMemberId())
.orElseGet(() -> {
MemberRefreshToken logoutMemberRenewRefreshToken = new MemberRefreshToken();
logoutMemberRenewRefreshToken.setMember(member);
return memberRefreshTokenRepository.save(logoutMemberRenewRefreshToken);
});

refreshTokenEntity.setRefreshToken(renewRefreshToken);
refreshTokenEntity.setMember(member);
String accessToken = tokenProvider.createAccessToken(member);
String refreshToken = tokenProvider.createRefreshToken(member);

memberRefreshTokenRepository.save(refreshTokenEntity);

RenewAccessTokenDto renewAccessTokenDto = tokenRenewService.renewAccessTokenDtoFromRefreshToken(renewRefreshToken);
String renewAccessToken = renewAccessTokenDto.renewAccessToken();
if (tokenRenewService.isBlacklisted(accessToken) || tokenRenewService.isBlacklisted(refreshToken)) {
throw new CustomException(ErrorCode.INVALID_TOKEN_EXCEPTION, ErrorCode.INVALID_TOKEN_EXCEPTION.getMessage());
}

AuthResDto resDto = AuthResDto.builder()
.accessToken(renewAccessToken)
.refreshToken(renewRefreshToken)
.build();
tokenRenewService.saveRefreshToken(refreshToken, member.getMemberId());
AuthResDto resDto = AuthResDto.of(accessToken, refreshToken);

return ApiResponseTemplate.success(SuccessCode.LOGIN_MEMBER_SUCCESS, resDto);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.skhu.moodfriend.app.domain.member.LoginType;
import com.skhu.moodfriend.app.domain.member.Member;
import com.skhu.moodfriend.app.repository.MemberRefreshTokenRepository;
import com.skhu.moodfriend.app.repository.MemberRepository;
import com.skhu.moodfriend.global.exception.CustomException;
import com.skhu.moodfriend.global.exception.code.ErrorCode;
Expand All @@ -18,6 +17,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.data.redis.core.RedisTemplate;

import java.security.Principal;
import java.util.HashMap;
Expand All @@ -27,8 +27,9 @@
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public class LogoutService {

private final MemberRefreshTokenRepository memberRefreshTokenRepository;
private final MemberRepository memberRepository;
private final TokenRenewService tokenRenewService;
private final RedisTemplate<String, String> redisTemplate;

@Value("${oauth.google.logout-url}")
private String googleLogoutUrl;
Expand All @@ -44,13 +45,18 @@ public ApiResponseTemplate<Void> logout(Principal principal) {
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_MEMBER_EXCEPTION, ErrorCode.NOT_FOUND_MEMBER_EXCEPTION.getMessage()));
LoginType loginType = member.getLoginType();

memberRefreshTokenRepository.findByMember_MemberId(memberId)
.ifPresent(memberRefreshTokenRepository::delete);
String refreshToken = redisTemplate.opsForValue().get(memberId.toString());
if (refreshToken != null) {
tokenRenewService.deleteRefreshToken(refreshToken);
}

if (principal instanceof Authentication) {
String accessToken = extractAccessToken((Authentication) principal);

if (accessToken != null) {
tokenRenewService.addToBlacklist(accessToken);
tokenRenewService.addToBlacklist(refreshToken);

switch (loginType) {
case GOOGLE_LOGIN:
logoutFromGoogle(accessToken);
Expand Down
Loading

0 comments on commit 3868491

Please sign in to comment.