Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public MemberResponse.LoginResponseDto testUser(HttpServletResponse response){
}

@PostMapping("/refresh")
public ResponseEntity<BaseResponse<?>> refreshToken(
public BaseResponse<?> refreshToken(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
public interface MemberService {
MemberResponse.LoginResponseDto googleLoginByToken(MemberRequest.GoogleLoginDto googleLoginDto, HttpServletResponse response);
MemberResponse.LoginResponseDto testLogin(HttpServletResponse response);
ResponseEntity<BaseResponse<?>> updateRefreshToken(HttpServletRequest request, HttpServletResponse response);
BaseResponse<?> updateRefreshToken(HttpServletRequest request, HttpServletResponse response);
Member getMember(MemberDetails memberDetails);
Member getMember(String email);
MemberResponse.MemberProfileDto getMemberProfile(MemberDetails memberDetails);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,18 @@ public MemberResponse.LoginResponseDto testLogin(HttpServletResponse response){

private void addTokenCookies(HttpServletResponse response, TokenResponse tokenResponse) {
// Access Token 쿠키
ResponseCookie accessCookie = ResponseCookie.from("ACCESS_TOKEN", tokenResponse.accessToken().token())
ResponseCookie accessCookie = ResponseCookie.from(JWT_ACCESS_TOKEN_COOKIE_NAME, tokenResponse.accessToken().token())
.httpOnly(true) // JS 접근 차단
.secure(true) // HTTPS 전용
.path("/") // 전체 경로에 대해 전송
.maxAge(ACCESS_TOKEN_EXPIRE_TIME) // 만료 시간
.sameSite("none") // CSRF 방어
.build();

ResponseCookie refreshCookie = ResponseCookie.from("REFRESH_TOKEN", tokenResponse.accessToken().token())
ResponseCookie refreshCookie = ResponseCookie.from(JWT_REFRESH_TOKEN_COOKIE_NAME, tokenResponse.accessToken().token())
.httpOnly(true)
.secure(true)
.path("/auth/refresh") // 리프레시 전용 엔드포인트에만 전송
.path("/member/refresh") // 리프레시 전용 엔드포인트에만 전송
.maxAge(REFRESH_TOKEN_EXPIRE_TIME)
.sameSite("none")
.build();
Expand Down Expand Up @@ -128,22 +128,23 @@ private TokenResponse getTokenResponse(HttpServletResponse response, Member memb
return tokenResponse;
}

public ResponseEntity<BaseResponse<?>> updateRefreshToken(HttpServletRequest request, HttpServletResponse response){
public BaseResponse<?> updateRefreshToken(HttpServletRequest request, HttpServletResponse response){
// 1) REFRESH_TOKEN 쿠키에서 값 꺼내기
String refreshToken = jwtProvider.resolveRefreshToken(request, JWT_REFRESH_TOKEN_COOKIE_NAME);

if (refreshToken == null) {
return ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.body(BaseResponse.onFailure("AUTH002", "리프레시 토큰이 없습니다", null));
return BaseResponse.onFailure(ErrorCode.EMPTY_TOKEN_PROVIDED,null);
}

// 2) 리프레시 토큰 유효성 검증
if (!jwtProvider.validateRefreshToken(refreshToken)) {
return ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.body(BaseResponse.onFailure("AUTH003", "리프레시 토큰이 유효하지 않습니다", null));
return BaseResponse.onFailure(ErrorCode.REFRESH_TOKEN_NOT_VALID,null);
}

String name = jwtProvider.parseAudience(refreshToken);
Member member = getMember(name);
MemberResponse.LoginResponseDto responseDto = MemberResponse.LoginResponseDto.from(member);

// 3) 토큰에서 Authentication 정보 추출
Authentication authentication = jwtProvider.getAuthentication(refreshToken);

Expand All @@ -159,7 +160,7 @@ public ResponseEntity<BaseResponse<?>> updateRefreshToken(HttpServletRequest req
.sameSite("none")
.build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return ResponseEntity.ok(BaseResponse.onSuccess("token 발급 완료"));
return BaseResponse.onSuccess(responseDto);
}

public Member getMember(MemberDetails memberDetails){
Expand Down Expand Up @@ -200,7 +201,7 @@ public MemberResponse.LoginResponseDto logout(MemberDetails memberDetails,HttpSe
MemberResponse.LoginResponseDto responseDto = MemberResponse.LoginResponseDto.from(member);

// 1) ACCESS_TOKEN 쿠키 삭제(값 비우고 maxAge=0)
ResponseCookie deleteAccess = ResponseCookie.from("ACCESS_TOKEN", "")
ResponseCookie deleteAccess = ResponseCookie.from(JWT_ACCESS_TOKEN_COOKIE_NAME, "")
.httpOnly(true)
.secure(true)
.path("/") // 로그인 시 지정한 path와 동일하게
Expand All @@ -209,10 +210,10 @@ public MemberResponse.LoginResponseDto logout(MemberDetails memberDetails,HttpSe
.build();

// 2) REFRESH_TOKEN 쿠키 삭제
ResponseCookie deleteRefresh = ResponseCookie.from("REFRESH_TOKEN", "")
ResponseCookie deleteRefresh = ResponseCookie.from(JWT_REFRESH_TOKEN_COOKIE_NAME, "")
.httpOnly(true)
.secure(true)
.path("/auth/refresh") // 로그인 시 지정한 path와 동일하게
.path("/member/refresh") // 로그인 시 지정한 path와 동일하게
.maxAge(0)
.sameSite("none")
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ public enum ErrorCode implements BaseCode {
EXPIRED_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "TOKEN-0000", "AccessToken 기간 만료됨"),
INVALID_TOKEN(HttpStatus.BAD_REQUEST, "TOKEN-0001", "토큰이 올바르지 않습니다."),
EMPTY_TOKEN_PROVIDED(HttpStatus.UNAUTHORIZED, "TOKEN-0002", "토큰 텅텅"),
REFRESH_TOKEN_NOT_VALID(HttpStatus.UNAUTHORIZED, "TOKEN-0003", "리프레시 토큰이 올바르지 않음"),



INVALID_EMAIL_OR_PASSWORD(HttpStatus.NOT_FOUND, "MEMBER-0001", "유효하지 않는 이메일, 비번"),
BAD_REQUEST_INGRANT(HttpStatus.BAD_REQUEST, "MEMBER-0002", "구글 권한이 제대로 넘어오지 않음."),
Expand Down