diff --git a/src/main/java/com/pickyfy/pickyfy/auth/filter/CustomLoginFilter.java b/src/main/java/com/pickyfy/pickyfy/auth/filter/CustomLoginFilter.java index 902fcff..af71b1e 100644 --- a/src/main/java/com/pickyfy/pickyfy/auth/filter/CustomLoginFilter.java +++ b/src/main/java/com/pickyfy/pickyfy/auth/filter/CustomLoginFilter.java @@ -59,12 +59,12 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR String accessToken = jwtUtil.createAccessToken(principal, role); String refreshToken = jwtUtil.createRefreshToken(principal, role); - redisUtil.setData("refresh:" + jwtUtil.getPrincipal(refreshToken), refreshToken, Constant.REFRESH_TOKEN_EXPIRATION_TIME); + redisUtil.setData("refresh:" + principal, refreshToken, Constant.REFRESH_TOKEN_EXPIRATION_TIME); setBody(role, response); - ResponseCookie accessCookie = createCookie("accessToken", accessToken, Constant.ACCESS_TOKEN_EXPIRATION_TIME, "/"); + ResponseCookie accessCookie = createCookie("accessToken", accessToken,"/"); response.addHeader(HttpHeaders.SET_COOKIE, accessCookie.toString()); - ResponseCookie refreshCookie = createCookie("refreshToken", refreshToken, Constant.REFRESH_TOKEN_EXPIRATION_TIME, "/auth"); + ResponseCookie refreshCookie = createCookie("refreshToken", refreshToken, "/auth"); response.addHeader(HttpHeaders.SET_COOKIE, refreshCookie.toString()); } @@ -84,13 +84,13 @@ private void setBody(String role, HttpServletResponse response) throws IOExcepti """, role)); } - private ResponseCookie createCookie(String name, String token, long expirationTime, String path) { + private ResponseCookie createCookie(String name, String token, String path) { return ResponseCookie.from(name, token) .httpOnly(true) .secure(true) .sameSite("None") .path(path) - .maxAge(Duration.ofMillis(expirationTime).getSeconds()) + .maxAge(Duration.ofMillis(Constant.COOKIE_EXPIRATION).getSeconds()) .build(); } } \ No newline at end of file diff --git a/src/main/java/com/pickyfy/pickyfy/auth/filter/JwtAuthFilter.java b/src/main/java/com/pickyfy/pickyfy/auth/filter/JwtAuthFilter.java index c8121a1..7adab87 100644 --- a/src/main/java/com/pickyfy/pickyfy/auth/filter/JwtAuthFilter.java +++ b/src/main/java/com/pickyfy/pickyfy/auth/filter/JwtAuthFilter.java @@ -2,6 +2,7 @@ import com.pickyfy.pickyfy.common.util.JwtUtil; import com.pickyfy.pickyfy.auth.details.CustomUserDetailsServiceImpl; +import com.pickyfy.pickyfy.web.dto.response.TokenValidationResult; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.Cookie; @@ -28,7 +29,14 @@ public class JwtAuthFilter extends OncePerRequestFilter { protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException { String token = getAccessTokenFromCookies(request); - if (token == null || !jwtUtil.validateToken(token)) { + if(token == null){ + filterChain.doFilter(request, response); + return; + } + + TokenValidationResult result = jwtUtil.validateTokenWithoutException(token); + if (!result.isValid()) { + request.setAttribute("errorMessage", result.message()); filterChain.doFilter(request, response); return; } diff --git a/src/main/java/com/pickyfy/pickyfy/auth/handler/CustomAuthenticationEntryPoint.java b/src/main/java/com/pickyfy/pickyfy/auth/handler/CustomAuthenticationEntryPoint.java index 8b6db8e..c0db9ad 100644 --- a/src/main/java/com/pickyfy/pickyfy/auth/handler/CustomAuthenticationEntryPoint.java +++ b/src/main/java/com/pickyfy/pickyfy/auth/handler/CustomAuthenticationEntryPoint.java @@ -6,26 +6,35 @@ import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; import java.io.IOException; +import java.util.Map; @Component public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { - String message = "인증 정보가 없습니다. 로그인 후 다시 시도하세요"; + String defaultMessage = "인증 정보가 없습니다. 로그인 후 다시 시도하세요"; + String defaultCode = "401"; + + Map errorCodeMapping = Map.of( + "유효하지 않은 토큰입니다.", "4012", + "토큰 만료", "4013" + ); + String message = (request.getAttribute("errorMessage") != null) + ? request.getAttribute("errorMessage").toString() + : defaultMessage; + + String code = errorCodeMapping.getOrDefault(message, defaultCode); - if(request.getAttribute("errorMessage") != null){ - message = request.getAttribute("errorMessage").toString(); - } response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(String.format(""" { "isSuccess": false, - "code": "401", + "code": "%s", "message": "%s" } - """, message)); + """, code, message)); } } \ No newline at end of file diff --git a/src/main/java/com/pickyfy/pickyfy/auth/handler/OAuth2SuccessHandler.java b/src/main/java/com/pickyfy/pickyfy/auth/handler/OAuth2SuccessHandler.java index 7c84e9e..0c33a1c 100644 --- a/src/main/java/com/pickyfy/pickyfy/auth/handler/OAuth2SuccessHandler.java +++ b/src/main/java/com/pickyfy/pickyfy/auth/handler/OAuth2SuccessHandler.java @@ -37,22 +37,22 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo redisUtil.setData("refresh:" + email, refreshToken, Constant.REFRESH_TOKEN_EXPIRATION_TIME); - ResponseCookie accessCookie = createCookie("accessToken", accessToken, Constant.ACCESS_TOKEN_EXPIRATION_TIME, "/"); + ResponseCookie accessCookie = createCookie("accessToken", accessToken, "/"); response.addHeader(HttpHeaders.SET_COOKIE, accessCookie.toString()); - ResponseCookie refreshCookie = createCookie("refreshToken", refreshToken, Constant.REFRESH_TOKEN_EXPIRATION_TIME, "/auth"); + ResponseCookie refreshCookie = createCookie("refreshToken", refreshToken, "/auth"); response.addHeader(HttpHeaders.SET_COOKIE, refreshCookie.toString()); response.sendRedirect(REDIRECT_URL); SecurityContextHolder.getContext().setAuthentication(authentication); } - private ResponseCookie createCookie(String name, String token, long expirationTime, String path) { + private ResponseCookie createCookie(String name, String token, String path) { return ResponseCookie.from(name, token) .httpOnly(true) .secure(true) .sameSite("None") .path(path) - .maxAge(Duration.ofMillis(expirationTime).getSeconds()) + .maxAge(Duration.ofMillis(Constant.COOKIE_EXPIRATION).getSeconds()) .build(); } } \ No newline at end of file diff --git a/src/main/java/com/pickyfy/pickyfy/common/Constant.java b/src/main/java/com/pickyfy/pickyfy/common/Constant.java index 6911102..73100fc 100644 --- a/src/main/java/com/pickyfy/pickyfy/common/Constant.java +++ b/src/main/java/com/pickyfy/pickyfy/common/Constant.java @@ -14,5 +14,7 @@ public class Constant { public static final long PLACES_EXPIRATION_TIME = 30 * 60 * 1000; public static final long PLACE_EXPIRATION_TIME = 30 * 60 * 1000; + public static final long COOKIE_EXPIRATION = 4 * 24 * 60 * 60 * 1000; + public static final String REDIS_KEY_PREFIX = "refresh:"; } diff --git a/src/main/java/com/pickyfy/pickyfy/common/config/SecurityConfig.java b/src/main/java/com/pickyfy/pickyfy/common/config/SecurityConfig.java index 10a7071..39a7119 100644 --- a/src/main/java/com/pickyfy/pickyfy/common/config/SecurityConfig.java +++ b/src/main/java/com/pickyfy/pickyfy/common/config/SecurityConfig.java @@ -54,7 +54,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .authorizeHttpRequests((auth) -> auth .requestMatchers("/", "/swagger-ui/**", "/v3/api-docs/**").permitAll() .requestMatchers("/users/signup", "/auth/login", "/email-auth/**", "/auth/reissue", "/users/verify-by-email", "/users/reset-password").permitAll() - .requestMatchers("/auth/oauth2/**", "/oauth2/callback", "/auth/me").permitAll() + .requestMatchers("/auth/oauth2/**", "/oauth2/callback", "/auth/me", "/auth/logout").permitAll() .requestMatchers("/actuator/**", "/actuator/prometheus").permitAll() .requestMatchers("/admin/**").hasAuthority("ADMIN") .anyRequest().authenticated() diff --git a/src/main/java/com/pickyfy/pickyfy/common/util/JwtUtil.java b/src/main/java/com/pickyfy/pickyfy/common/util/JwtUtil.java index d406e88..110e9de 100644 --- a/src/main/java/com/pickyfy/pickyfy/common/util/JwtUtil.java +++ b/src/main/java/com/pickyfy/pickyfy/common/util/JwtUtil.java @@ -3,6 +3,7 @@ import com.pickyfy.pickyfy.web.apiResponse.error.ErrorStatus; import com.pickyfy.pickyfy.common.Constant; import com.pickyfy.pickyfy.exception.ExceptionHandler; +import com.pickyfy.pickyfy.web.dto.response.TokenValidationResult; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; @@ -14,6 +15,8 @@ import javax.crypto.SecretKey; import java.security.Key; import java.util.Date; +import java.util.HashMap; +import java.util.Map; @Slf4j @Component @@ -72,21 +75,42 @@ private String createToken(String principal, String role, long expireTime, Strin .compact(); } - public boolean validateToken(String token) { // 예외처리 추가 + public void validateToken(String token) { try { Jwts.parser().verifyWith((SecretKey) key).build().parseSignedClaims(token); - return true; - } catch (SecurityException | MalformedJwtException e) { - log.info("잘못된 서명 혹은 JWT 형식 오류", e); - } catch (ExpiredJwtException e) { - log.info("토큰 만료", e); - throw new ExceptionHandler(ErrorStatus.TOKEN_EXPIRATION); - } catch (UnsupportedJwtException e) { - log.info("지원하지 않는 서명 알고리즘", e); - } catch (IllegalArgumentException e) { - log.info("올바르지 않은 값 입력(토큰 문자열 null)", e); + TokenValidationResult.success("검증 완료."); + } catch (Exception e) { + handleJwtException(e, true); + } + } + + public TokenValidationResult validateTokenWithoutException(String token) { + try { + Jwts.parser().verifyWith((SecretKey) key).build().parseSignedClaims(token); + return TokenValidationResult.success("검증 완료."); + } catch (Exception e) { + return handleJwtException(e, false); + } + } + + private TokenValidationResult handleJwtException(Exception e, boolean throwException) { + Map, String> errorMessages = new HashMap<>(); + errorMessages.put(SecurityException.class, "유효하지 않은 토큰입니다."); + errorMessages.put(MalformedJwtException.class, "유효하지 않은 토큰입니다."); + errorMessages.put(UnsupportedJwtException.class, "유효하지 않은 토큰입니다."); + errorMessages.put(IllegalArgumentException.class, "유효하지 않은 토큰입니다."); + errorMessages.put(ExpiredJwtException.class, "토큰 만료"); + + String message = errorMessages.getOrDefault(e.getClass(), "알 수 없는 JWT 오류"); + log.info(message, e); + + if (throwException) { + throw new ExceptionHandler( + e instanceof ExpiredJwtException ? ErrorStatus.TOKEN_EXPIRATION : ErrorStatus.TOKEN_INVALID + ); } - return false; + + return TokenValidationResult.failure(message); } public Claims parseClaims(String token) { @@ -108,5 +132,4 @@ public String getPrincipal(String token) { public String getRole(String token) { return parseClaims(token).get(ROLE, String.class); } - } \ No newline at end of file diff --git a/src/main/java/com/pickyfy/pickyfy/exception/DuplicateResourceException.java b/src/main/java/com/pickyfy/pickyfy/exception/DuplicateResourceException.java index 403913c..a08f908 100644 --- a/src/main/java/com/pickyfy/pickyfy/exception/DuplicateResourceException.java +++ b/src/main/java/com/pickyfy/pickyfy/exception/DuplicateResourceException.java @@ -1,9 +1,9 @@ package com.pickyfy.pickyfy.exception; -import com.pickyfy.pickyfy.web.apiResponse.common.BaseErrorCode; +import com.pickyfy.pickyfy.web.apiResponse.error.ErrorStatus; public class DuplicateResourceException extends GeneralException { - public DuplicateResourceException(BaseErrorCode baseErrorCode) { - super(baseErrorCode); + public DuplicateResourceException(ErrorStatus errorStatus) { + super(errorStatus); } } diff --git a/src/main/java/com/pickyfy/pickyfy/exception/ExceptionHandler.java b/src/main/java/com/pickyfy/pickyfy/exception/ExceptionHandler.java index a904197..3e0eb7d 100644 --- a/src/main/java/com/pickyfy/pickyfy/exception/ExceptionHandler.java +++ b/src/main/java/com/pickyfy/pickyfy/exception/ExceptionHandler.java @@ -1,9 +1,9 @@ package com.pickyfy.pickyfy.exception; -import com.pickyfy.pickyfy.web.apiResponse.common.BaseErrorCode; +import com.pickyfy.pickyfy.web.apiResponse.error.ErrorStatus; public class ExceptionHandler extends GeneralException { - public ExceptionHandler(BaseErrorCode errorCode){ - super(errorCode); + public ExceptionHandler(ErrorStatus errorStatus){ + super(errorStatus); } } \ No newline at end of file diff --git a/src/main/java/com/pickyfy/pickyfy/exception/GeneralException.java b/src/main/java/com/pickyfy/pickyfy/exception/GeneralException.java index 5db0c33..1fee476 100644 --- a/src/main/java/com/pickyfy/pickyfy/exception/GeneralException.java +++ b/src/main/java/com/pickyfy/pickyfy/exception/GeneralException.java @@ -1,17 +1,11 @@ package com.pickyfy.pickyfy.exception; -import com.pickyfy.pickyfy.web.apiResponse.common.BaseErrorCode; -import com.pickyfy.pickyfy.web.apiResponse.error.ErrorResponse; +import com.pickyfy.pickyfy.web.apiResponse.error.ErrorStatus; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor public class GeneralException extends RuntimeException { - - private BaseErrorCode code; - - public ErrorResponse getErrorReason(){ - return this.code.getReason(); - } + private final ErrorStatus errorStatus; } diff --git a/src/main/java/com/pickyfy/pickyfy/exception/GlobalExceptionHandler.java b/src/main/java/com/pickyfy/pickyfy/exception/GlobalExceptionHandler.java index 11c3795..e5eecc0 100644 --- a/src/main/java/com/pickyfy/pickyfy/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/pickyfy/pickyfy/exception/GlobalExceptionHandler.java @@ -1,9 +1,9 @@ package com.pickyfy.pickyfy.exception; import com.pickyfy.pickyfy.web.apiResponse.common.ApiResponse; -import com.pickyfy.pickyfy.web.apiResponse.error.ErrorResponse; import com.pickyfy.pickyfy.web.apiResponse.error.ErrorStatus; import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolation; import lombok.extern.slf4j.Slf4j; import jakarta.validation.ConstraintViolationException; import org.springframework.http.HttpHeaders; @@ -29,7 +29,7 @@ public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler public ResponseEntity handleConstraintViolation(ConstraintViolationException e, WebRequest request){ String errorMessage = e.getConstraintViolations().stream() - .map(constraintViolation -> constraintViolation.getMessage()) + .map(ConstraintViolation::getMessage) .findFirst() .orElseThrow(() -> new RuntimeException("ConstraintViolationException 추출 도중 에러 발생")); @@ -41,7 +41,7 @@ public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotVali Map errors = new LinkedHashMap<>(); - e.getBindingResult().getFieldErrors().stream() + e.getBindingResult().getFieldErrors() .forEach(fieldError -> { String fieldName = fieldError.getField(); String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse(""); @@ -52,9 +52,8 @@ public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotVali } @ExceptionHandler(value = GeneralException.class) - public ResponseEntity handleOnThrowException(GeneralException generalException, HttpServletRequest request) { - ErrorResponse errorReasonHttpStatus = generalException.getErrorReason(); - return buildOnThrowExceptionResponse(generalException,errorReasonHttpStatus,null,request); + public ResponseEntity handleOnThrowException(GeneralException generalException, HttpServletRequest request) { + return buildOnThrowExceptionResponse(generalException, generalException.getErrorStatus(),null, request); } @ExceptionHandler @@ -63,33 +62,34 @@ public ResponseEntity handleUnexpectedException(Exception e, WebRequest return buildUnexpectedExceptionResponse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(),request, e.getMessage()); } - private ResponseEntity buildConstraintViolationResponse(Exception e, ErrorStatus errorCommonStatus, - HttpHeaders headers, WebRequest request) { - ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null); + private ResponseEntity buildConstraintViolationResponse(Exception e, ErrorStatus errorStatus, + HttpHeaders headers, WebRequest request) { + ApiResponse body = ApiResponse.onFailure(errorStatus, null); return super.handleExceptionInternal( e, body, headers, - errorCommonStatus.getHttpStatus(), + errorStatus.getHttpStatus(), request ); } - private ResponseEntity buildInvalidMethodArgumentResponse(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus, - WebRequest request, Map errorArgs) { - ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorArgs); + private ResponseEntity buildInvalidMethodArgumentResponse(Exception e, HttpHeaders headers, ErrorStatus errorStatus, + WebRequest request, Map errorArgs) { + + ApiResponse body = ApiResponse.onFailure(errorStatus, errorArgs); return super.handleExceptionInternal( e, body, headers, - errorCommonStatus.getHttpStatus(), + errorStatus.getHttpStatus(), request ); } - private ResponseEntity buildUnexpectedExceptionResponse(Exception e, ErrorStatus errorCommonStatus, - HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) { - ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorPoint); + private ResponseEntity buildUnexpectedExceptionResponse(Exception e, ErrorStatus errorStatus, + HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) { + ApiResponse body = ApiResponse.onFailure(errorStatus, errorPoint); return super.handleExceptionInternal( e, body, @@ -99,18 +99,18 @@ private ResponseEntity buildUnexpectedExceptionResponse(Exception e, Err ); } - private ResponseEntity buildOnThrowExceptionResponse(Exception e, ErrorResponse reason, - HttpHeaders headers, HttpServletRequest request) { + private ResponseEntity buildOnThrowExceptionResponse(Exception e, ErrorStatus errorStatus, + HttpHeaders headers, HttpServletRequest request) { - ApiResponse body = ApiResponse.onFailure(reason.getCode(),reason.getMessage(),null); + ApiResponse body = ApiResponse.onFailure(errorStatus, null); WebRequest webRequest = new ServletWebRequest(request); return super.handleExceptionInternal( e, body, headers, - null, + errorStatus.getHttpStatus(), webRequest ); } -} \ No newline at end of file +} diff --git a/src/main/java/com/pickyfy/pickyfy/exception/InvalidRefreshTokenException.java b/src/main/java/com/pickyfy/pickyfy/exception/InvalidRefreshTokenException.java new file mode 100644 index 0000000..cdd2f1b --- /dev/null +++ b/src/main/java/com/pickyfy/pickyfy/exception/InvalidRefreshTokenException.java @@ -0,0 +1,9 @@ +package com.pickyfy.pickyfy.exception; + +import com.pickyfy.pickyfy.web.apiResponse.error.ErrorStatus; + +public class InvalidRefreshTokenException extends GeneralException { + public InvalidRefreshTokenException(ErrorStatus errorStatus) { + super(errorStatus); + } +} diff --git a/src/main/java/com/pickyfy/pickyfy/service/AuthServiceImpl.java b/src/main/java/com/pickyfy/pickyfy/service/AuthServiceImpl.java index 691b7e2..fa93bf7 100644 --- a/src/main/java/com/pickyfy/pickyfy/service/AuthServiceImpl.java +++ b/src/main/java/com/pickyfy/pickyfy/service/AuthServiceImpl.java @@ -28,16 +28,16 @@ public AuthResponse reIssue(String token){ String accessToken = jwtUtil.createAccessToken(principal, jwtUtil.getRole(token)); String refreshToken = jwtUtil.createRefreshToken(principal, jwtUtil.getRole(token)); - redisUtil.setData("refresh:" + jwtUtil.getPrincipal(refreshToken), refreshToken, Constant.REFRESH_TOKEN_EXPIRATION_TIME); + redisUtil.setData("refresh:" + principal, refreshToken, Constant.REFRESH_TOKEN_EXPIRATION_TIME); return AuthResponse.from(accessToken, refreshToken); - } + } @Override public boolean isAuthenticated(String accessToken) { - return jwtUtil.validateToken(accessToken); + return jwtUtil.validateTokenWithoutException(accessToken).isValid(); } - public void validateRefreshToken(String token){ + public void validateRefreshToken(String token) { jwtUtil.validateToken(token); String getToken = redisUtil.getData("refresh:" + jwtUtil.getPrincipal(token)); if(!token.equals(getToken)){ diff --git a/src/main/java/com/pickyfy/pickyfy/web/apiResponse/common/ApiResponse.java b/src/main/java/com/pickyfy/pickyfy/web/apiResponse/common/ApiResponse.java index a037b4b..d264a56 100644 --- a/src/main/java/com/pickyfy/pickyfy/web/apiResponse/common/ApiResponse.java +++ b/src/main/java/com/pickyfy/pickyfy/web/apiResponse/common/ApiResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.pickyfy.pickyfy.web.apiResponse.error.ErrorStatus; import com.pickyfy.pickyfy.web.apiResponse.success.SuccessStatus; import lombok.AllArgsConstructor; import lombok.Getter; @@ -25,7 +26,11 @@ public static ApiResponse onSuccess(SuccessStatus status, T result) { return new ApiResponse<>(true, status.getCode(), status.getMessage(), result); } - public static ApiResponse onFailure(String code, String message, T data){ - return new ApiResponse<>(false, code, message, data); + public static ApiResponse onFailure(T result){ + return new ApiResponse<>(false, ErrorStatus._INTERNAL_SERVER_ERROR.getCode(), ErrorStatus._INTERNAL_SERVER_ERROR.getMessage(), result); + } + + public static ApiResponse onFailure(ErrorStatus status, T result){ + return new ApiResponse<>(false, status.getCode(), status.getMessage(), result); } } diff --git a/src/main/java/com/pickyfy/pickyfy/web/controller/AuthController.java b/src/main/java/com/pickyfy/pickyfy/web/controller/AuthController.java index 6b133a6..1658ee9 100644 --- a/src/main/java/com/pickyfy/pickyfy/web/controller/AuthController.java +++ b/src/main/java/com/pickyfy/pickyfy/web/controller/AuthController.java @@ -1,8 +1,10 @@ package com.pickyfy.pickyfy.web.controller; import com.pickyfy.pickyfy.common.Constant; +import com.pickyfy.pickyfy.exception.InvalidRefreshTokenException; import com.pickyfy.pickyfy.service.AuthService; import com.pickyfy.pickyfy.web.apiResponse.common.ApiResponse; +import com.pickyfy.pickyfy.web.apiResponse.error.ErrorStatus; import com.pickyfy.pickyfy.web.apiResponse.success.SuccessStatus; import com.pickyfy.pickyfy.web.dto.response.AuthResponse; import io.swagger.v3.oas.annotations.Parameter; @@ -42,12 +44,10 @@ public ApiResponse reIssue( HttpServletResponse response) { if (refreshToken == null) { - return ApiResponse.onFailure("400","리프레시 토큰이 없습니다.", null); + throw new InvalidRefreshTokenException(ErrorStatus.TOKEN_INVALID); } AuthResponse authResponse = authService.reIssue(refreshToken); - response.setHeader("Authorization", "Bearer " + authResponse.accessToken()); - createCookie(response, authResponse.refreshToken()); - + createCookie(response, authResponse); return ApiResponse.onSuccess(SuccessStatus.REISSUE_TOKEN_SUCCESS, null); } @@ -59,16 +59,25 @@ public ApiResponse isAuthenticated( return ApiResponse.onSuccess(isAuthenticated); } - private void createCookie(HttpServletResponse response, String refreshToken) { - ResponseCookie expiredCookie = ResponseCookie.from(REFRESH_TOKEN_COOKIE_NAME, refreshToken) + private void createCookie(HttpServletResponse response, AuthResponse token) { + ResponseCookie expiredAccessToken = ResponseCookie.from(ACCESS_TOKEN_COOKIE_NAME, token.accessToken()) .httpOnly(true) .secure(true) .sameSite("None") .path("/") - .maxAge(Duration.ofMillis(Constant.REFRESH_TOKEN_EXPIRATION_TIME).getSeconds()) + .maxAge(Duration.ofMillis(Constant.COOKIE_EXPIRATION).getSeconds()) .build(); - response.setHeader(HttpHeaders.SET_COOKIE, expiredCookie.toString()); + ResponseCookie expiredRefreshToken = ResponseCookie.from(REFRESH_TOKEN_COOKIE_NAME, token.refreshToken()) + .httpOnly(true) + .secure(true) + .sameSite("None") + .path("/auth") + .maxAge(Duration.ofMillis(Constant.COOKIE_EXPIRATION).getSeconds()) + .build(); + + response.addHeader(HttpHeaders.SET_COOKIE, expiredAccessToken.toString()); + response.addHeader(HttpHeaders.SET_COOKIE, expiredRefreshToken.toString()); } private void clearCookie(HttpServletResponse response) { @@ -91,4 +100,4 @@ private void clearCookie(HttpServletResponse response) { response.addHeader(HttpHeaders.SET_COOKIE, expiredAccessToken.toString()); response.addHeader(HttpHeaders.SET_COOKIE, expiredRefreshToken.toString()); } -} +} \ No newline at end of file diff --git a/src/main/java/com/pickyfy/pickyfy/web/dto/response/TokenValidationResult.java b/src/main/java/com/pickyfy/pickyfy/web/dto/response/TokenValidationResult.java new file mode 100644 index 0000000..46486a2 --- /dev/null +++ b/src/main/java/com/pickyfy/pickyfy/web/dto/response/TokenValidationResult.java @@ -0,0 +1,11 @@ +package com.pickyfy.pickyfy.web.dto.response; + +public record TokenValidationResult(boolean isValid, String message) { + public static TokenValidationResult success(String message) { + return new TokenValidationResult(true, message); + } + + public static TokenValidationResult failure(String message) { + return new TokenValidationResult(false, message); + } +} \ No newline at end of file