Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat-be: log 커밋 revert #934

Merged
merged 1 commit into from
Oct 24, 2024
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
36 changes: 3 additions & 33 deletions backend/src/main/java/com/cruru/auth/service/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
import com.cruru.member.domain.MemberRole;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import java.util.HashMap;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
Expand All @@ -33,140 +32,111 @@ public class AuthService {
private final TokenRedisClient tokenRedisClient;

public Token createAccessToken(String email, MemberRole role) {
log.info("Creating access token for email: {}, role: {}", email, role);
Map<String, Object> claims = getClaims(email, role);
String token = tokenProvider.createToken(claims, tokenProperties.accessExpireLength());
log.debug("Access token created: {}", token);
return new AccessToken(token);
}

@Transactional
public Token createRefreshToken(String email, MemberRole role) {
log.info("Creating refresh token for email: {}", email);
if (tokenRedisClient.existsByEmail(email)) {
log.debug("Existing refresh token found, rotating token");
return rotateRefreshToken(email, role);
}

Map<String, Object> claims = getClaims(email, role);
String token = tokenProvider.createToken(claims, tokenProperties.refreshExpireLength());
tokenRedisClient.saveToken(email, token);
log.debug("New refresh token created and saved to Redis: {}", token);

return new RefreshToken(token, email);
}

@Transactional
public TokenResponse refresh(String refreshToken) {
log.info("Refreshing tokens using refresh token");
String email = extractEmail(refreshToken);
checkRefreshTokenExists(email, refreshToken);
MemberRole role = MemberRole.valueOf(extractMemberRole(refreshToken));
validMemberRefreshToken(refreshToken, email);
log.debug("Refresh token valid, rotating tokens");
return rotateTokens(email, role);
}

private void checkRefreshTokenExists(String email, String refreshToken) {
log.info("Checking if refresh token exists for email: {}", email);
if (!isTokenSignatureValid(refreshToken)) {
log.error("Refresh token signature is invalid for token: {}", refreshToken);
throw new IllegalTokenException();
}

if (!tokenRedisClient.existsByToken(email, refreshToken)) {
log.error("Refresh token does not exist in Redis for email: {}", email);
throw new IllegalTokenException();
}

if (isTokenExpired(refreshToken)) {
log.warn("Refresh token expired for email: {}", email);
throw new LoginExpiredException();
}
}

private TokenResponse rotateTokens(String email, MemberRole role) {
log.info("Rotating access and refresh tokens for email: {}", email);
Token accessToken = createAccessToken(email, role);
Token refreshToken = rotateRefreshToken(email, role);
log.debug("Tokens rotated successfully for email: {}", email);
return new TokenResponse(accessToken.getToken(), refreshToken.getToken());
}

private Token rotateRefreshToken(String email, MemberRole role) {
log.info("Rotating refresh token for email: {}", email);
Map<String, Object> claims = getClaims(email, role);
String token = tokenProvider.createToken(claims, tokenProperties.refreshExpireLength());
RefreshToken refreshToken = new RefreshToken(token, email);

tokenRedisClient.saveToken(email, refreshToken.getToken());
log.debug("New refresh token saved to Redis: {}", refreshToken.getToken());
return refreshToken;
}

private Map<String, Object> getClaims(String email, MemberRole role) {
log.debug("Creating claims for email: {}, role: {}", email, role);
return Map.of(
EMAIL_CLAIM, email,
ROLE_CLAIM, role.name()
);
}

public boolean isTokenExpired(String token) {
log.debug("Checking if token is expired: {}", token);
return tokenProvider.isTokenExpired(token);
}

public boolean isTokenSignatureValid(String token) {
log.debug("Checking if token signature is valid: {}", token);
try {
return tokenProvider.isSignatureValid(token);
} catch (IllegalTokenException e) {
log.error("Token signature is invalid: {}", token, e);
return false;
}
}

public String extractEmail(String token) {
log.debug("Extracting email from token");
return extractClaim(token, EMAIL_CLAIM);
}

public String extractMemberRole(String token) {
log.debug("Extracting member role from token");
return extractClaim(token, ROLE_CLAIM);
}

private String extractClaim(String token, String key) {
log.debug("Extracting claim: {} from token", key);
String claim;
try {
claim = tokenProvider.extractClaim(token, key);
} catch (ExpiredJwtException e) {
Claims claims = e.getClaims();
log.warn("Token expired, extracting claim from expired token");
return claims.get(key, String.class);
}
if (claim == null) {
log.error("Claim {} not found in token", key);
throw new IllegalTokenException();
}
return claim;
}

public boolean isNotVerifiedPassword(String rawPassword, String encodedPassword) {
log.debug("Validating password");
return !passwordValidator.matches(rawPassword, encodedPassword);
}

private void validMemberRefreshToken(String refreshToken, String email) {
log.debug("Validating refresh token for email: {}", email);
String foundToken = tokenRedisClient.getToken(email)
.orElseThrow(() -> {
log.error("Refresh token not found in Redis for email: {}", email);
return new IllegalTokenException();
});
.orElseThrow(IllegalTokenException::new);
if (!foundToken.equals(refreshToken)) {
log.error("Refresh token does not match the one in Redis for email: {}", email);
throw new IllegalTokenException();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseCookie;
import org.springframework.web.servlet.HandlerInterceptor;

@Slf4j
@RequiredArgsConstructor
public class AuthenticationInterceptor implements HandlerInterceptor {

Expand All @@ -25,85 +23,61 @@ public class AuthenticationInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
log.info("Request URI: {}, Method: {}", request.getRequestURI(), request.getMethod()); // 로그 추가

if (isGetApplyformRequest(request)) {
log.info("GET applyform request is allowed");
return true;
}

if (isOptionsRequest(request) || isAuthenticated(request)) {
log.info("OPTIONS request or valid authentication");
return true;
}

if (isValidTokenExpired(request)) {
log.info("Token expired, attempting refresh...");
refresh(request, response);
return true;
}

log.warn("Unauthorized request: {}", request.getRequestURI());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}

private void refresh(HttpServletRequest request, HttpServletResponse response) {
String token = cookieManager.extractRefreshToken(request);
log.info("Refresh token extracted: {}", token);

TokenResponse tokenResponse = authService.refresh(token);

ResponseCookie accessTokenCookie = cookieManager.createAccessTokenCookie(tokenResponse.accessToken());
ResponseCookie refreshTokenCookie = cookieManager.createRefreshTokenCookie(tokenResponse.refreshToken());

log.info("New access and refresh tokens created");

response.addHeader(HttpHeaders.SET_COOKIE, accessTokenCookie.toString());
response.addHeader(HttpHeaders.SET_COOKIE, refreshTokenCookie.toString());
}

private boolean isGetApplyformRequest(HttpServletRequest request) {
boolean result = request.getRequestURI().matches(APPLYFORM_REQUEST_URI) && isGetRequest(request);
log.info("Is GET applyform request: {}", result);
return result;
return request.getRequestURI().matches(APPLYFORM_REQUEST_URI) && isGetRequest(request);
}

private boolean isOptionsRequest(HttpServletRequest request) {
boolean result = HttpMethod.OPTIONS.name().equalsIgnoreCase(request.getMethod());
log.info("Is OPTIONS request: {}", result);
return result;
return HttpMethod.OPTIONS.name().equalsIgnoreCase(request.getMethod());
}

private boolean isAuthenticated(HttpServletRequest request) {
try {
String token = cookieManager.extractAccessToken(request);
log.info("Access token extracted: {}", token);
boolean valid = authService.isTokenSignatureValid(token) && !authService.isTokenExpired(token);
log.info("Is authenticated: {}", valid);
return valid;
return authService.isTokenSignatureValid(token) && !authService.isTokenExpired(token);
} catch (IllegalCookieException e) {
log.error("Illegal cookie exception", e);
throw new LoginUnauthorizedException();
}
}

private boolean isValidTokenExpired(HttpServletRequest request) {
try {
String token = cookieManager.extractAccessToken(request);
log.info("Access token extracted: {}", token);
boolean expired = authService.isTokenSignatureValid(token) && authService.isTokenExpired(token);
log.info("Is token expired: {}", expired);
return expired;
return authService.isTokenSignatureValid(token) && authService.isTokenExpired(token);
} catch (IllegalCookieException e) {
log.error("Illegal cookie exception", e);
throw new LoginUnauthorizedException();
}
}

private boolean isGetRequest(HttpServletRequest request) {
boolean result = HttpMethod.GET.name().equalsIgnoreCase(request.getMethod());
log.info("Is GET request: {}", result);
return result;
return HttpMethod.GET.name().equalsIgnoreCase(request.getMethod());
}
}
44 changes: 8 additions & 36 deletions backend/src/main/java/com/cruru/global/util/CookieManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,119 +5,91 @@
import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@RequiredArgsConstructor
public class CookieManager {

private final CookieProperties cookieProperties;

public String extractAccessToken(HttpServletRequest request) {
log.info("Extracting access token from cookies");
Cookie[] cookies = extractCookie(request);
return Arrays.stream(cookies)
.filter(this::isAccessTokenCookie)
.findFirst()
.map(Cookie::getValue)
.orElseThrow(() -> {
log.error("Access token cookie not found or invalid");
return new IllegalCookieException();
});
.orElseThrow(IllegalCookieException::new);
}

private Cookie[] extractCookie(HttpServletRequest request) {
log.debug("Extracting cookies from request");
Cookie[] cookies = request.getCookies();

if (cookies == null) {
log.warn("No cookies found in the request");
throw new IllegalCookieException();
}
return cookies;
}

private boolean isAccessTokenCookie(Cookie cookie) {
boolean result = cookieProperties.accessTokenKey().equals(cookie.getName());
log.debug("Is access token cookie: {}", result);
return result;
return cookieProperties.accessTokenKey().equals(cookie.getName());
}

public String extractRefreshToken(HttpServletRequest request) {
log.info("Extracting refresh token from cookies");
Cookie[] cookies = extractCookie(request);
return Arrays.stream(cookies)
.filter(this::isRefreshTokenCookie)
.findFirst()
.map(Cookie::getValue)
.orElseThrow(() -> {
log.error("Refresh token cookie not found or invalid");
return new IllegalCookieException();
});
.orElseThrow(IllegalCookieException::new);
}

private boolean isRefreshTokenCookie(Cookie cookie) {
boolean result = cookieProperties.refreshTokenKey().equals(cookie.getName());
log.debug("Is refresh token cookie: {}", result);
return result;
return cookieProperties.refreshTokenKey().equals(cookie.getName());
}

public ResponseCookie createAccessTokenCookie(String token) {
log.info("Creating access token cookie");
ResponseCookie cookie = ResponseCookie.from(cookieProperties.accessTokenKey(), token)
return ResponseCookie.from(cookieProperties.accessTokenKey(), token)
.httpOnly(cookieProperties.httpOnly())
.secure(cookieProperties.secure())
.domain(cookieProperties.domain())
.path(cookieProperties.path())
.sameSite(cookieProperties.sameSite())
.maxAge(cookieProperties.maxAge())
.build();
log.debug("Access token cookie created: {}", cookie);
return cookie;
}

public ResponseCookie createRefreshTokenCookie(String refreshToken) {
log.info("Creating refresh token cookie");
ResponseCookie cookie = ResponseCookie.from(cookieProperties.refreshTokenKey(), refreshToken)
return ResponseCookie.from(cookieProperties.refreshTokenKey(), refreshToken)
.httpOnly(cookieProperties.httpOnly())
.secure(cookieProperties.secure())
.domain(cookieProperties.domain())
.path(cookieProperties.path())
.sameSite(cookieProperties.sameSite())
.maxAge(cookieProperties.maxAge())
.build();
log.debug("Refresh token cookie created: {}", cookie);
return cookie;
}

public ResponseCookie clearAccessTokenCookie() {
log.info("Clearing access token cookie");
ResponseCookie cookie = ResponseCookie.from(cookieProperties.accessTokenKey())
return ResponseCookie.from(cookieProperties.accessTokenKey())
.httpOnly(cookieProperties.httpOnly())
.secure(cookieProperties.secure())
.domain(cookieProperties.domain())
.path(cookieProperties.path())
.sameSite(cookieProperties.sameSite())
.maxAge(0)
.build();
log.debug("Access token cookie cleared: {}", cookie);
return cookie;
}

public ResponseCookie clearRefreshTokenCookie() {
log.info("Clearing refresh token cookie");
ResponseCookie cookie = ResponseCookie.from(cookieProperties.refreshTokenKey())
return ResponseCookie.from(cookieProperties.refreshTokenKey())
.httpOnly(cookieProperties.httpOnly())
.secure(cookieProperties.secure())
.domain(cookieProperties.domain())
.path(cookieProperties.path())
.sameSite(cookieProperties.sameSite())
.maxAge(0)
.build();
log.debug("Refresh token cookie cleared: {}", cookie);
return cookie;
}
}