diff --git a/src/main/java/com/mpnp/baechelin/oauth/common/AuthResponse.java b/src/main/java/com/mpnp/baechelin/oauth/common/AuthResponse.java index 78979ca..f8d6a7f 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/common/AuthResponse.java +++ b/src/main/java/com/mpnp/baechelin/oauth/common/AuthResponse.java @@ -23,6 +23,7 @@ public static AuthResponse success(String name, T body) { ErrorCode.SUCCESS_MESSAGE.getMessage()), map); } + // 이 밑에 코드는 전부 exception 으로 빼기 public static AuthResponse fail() { return new AuthResponse<>(new AuthResponseHeader( ErrorCode.FAILED_MESSAGE.getCode(), diff --git a/src/main/java/com/mpnp/baechelin/oauth/common/AuthResponseHeader.java b/src/main/java/com/mpnp/baechelin/oauth/common/AuthResponseHeader.java index 6af1325..f5f775c 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/common/AuthResponseHeader.java +++ b/src/main/java/com/mpnp/baechelin/oauth/common/AuthResponseHeader.java @@ -9,6 +9,6 @@ @Setter @AllArgsConstructor public class AuthResponseHeader { - private int code; + private String code; private String message; } diff --git a/src/main/java/com/mpnp/baechelin/oauth/exception/ErrorCode.java b/src/main/java/com/mpnp/baechelin/oauth/exception/ErrorCode.java index 499010c..1978e3b 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/exception/ErrorCode.java +++ b/src/main/java/com/mpnp/baechelin/oauth/exception/ErrorCode.java @@ -7,17 +7,20 @@ @RequiredArgsConstructor public enum ErrorCode { - SUCCESS_MESSAGE(200, "SUCCESS"), - NOT_FOUND_MESSAGE(500, "NOT FOUND"), - FAILED_MESSAGE(500, "서버에서 오류가 발생하였습니다."), - INVALID_ACCESS_TOKEN(401, "유효하지 않은 Access Token입니다."), - INVALID_REFRESH_TOKEN(401, "유효하지 않은 Refresh Token입니다."), - NOT_EXPIRED_TOKEN_YET(401,"만료되지 않은 JWT 토큰입니다."), - EXPIRED_TOKEN(401, "만료된 JWT 토큰입니다."), - WRONG_TYPE_TOKEN(401, "잘못된 JWT 토큰입니다."), - ACCESS_DENIED(401, "접근이 거부되었습니다."), - ALREADY_LOGIN_ACCOUNT(400, "ALREADY_LOGIN_ACCOUNT"); + SUCCESS_MESSAGE(200, "S-SUC200","SUCCESS"), +// NOT_FOUND_MESSAGE(500, "BE001", "NOT FOUND"), + FAILED_MESSAGE(500, "E-FAI500","서버에서 오류가 발생하였습니다."), + INVALID_ACCESS_TOKEN(401, "E-IAT401","유효하지 않은 Access Token입니다."), + INVALID_REFRESH_TOKEN(401, "E-IRT401", "유효하지 않은 Refresh Token입니다."), + NOT_EXPIRED_TOKEN_YET(401, "E-NET401", "만료되지 않은 JWT 토큰입니다."), + EXPIRED_TOKEN(401, "E-EXT401", "만료된 JWT 토큰입니다."), + WRONG_TYPE_TOKEN(401, "E-WTT401","잘못된 JWT 토큰입니다."), + WRONG_TYPE_SIGNATURE(401, "E-WTS401", "잘못된 JWT 서명입니다."), + ACCESS_DENIED(401, "E-ACD401","접근이 거부되었습니다."), + TOKEN_NOT_EXIST(401, "E-TNE401", "토큰이 존재하지 않습니다."), + ALREADY_LOGIN_ACCOUNT(400, "E-ALA400","다른 계정으로 로그인 되었습니다."); - private final int code; + private final int status; + private final String code; private final String message; } diff --git a/src/main/java/com/mpnp/baechelin/oauth/exception/RestAuthenticationEntryPoint.java b/src/main/java/com/mpnp/baechelin/oauth/exception/RestAuthenticationEntryPoint.java index 739e2b8..8280b83 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/exception/RestAuthenticationEntryPoint.java +++ b/src/main/java/com/mpnp/baechelin/oauth/exception/RestAuthenticationEntryPoint.java @@ -20,7 +20,7 @@ public void commence( HttpServletResponse response, AuthenticationException authException ) throws IOException { - String exception = (String)request.getAttribute("javax.servlet.error.exception"); + String exception = (String)request.getAttribute("exception"); if(exception == null) { setResponse(response, ErrorCode.FAILED_MESSAGE); @@ -29,12 +29,15 @@ public void commence( else if(exception.equals(ErrorCode.WRONG_TYPE_TOKEN.getCode())) { setResponse(response, ErrorCode.WRONG_TYPE_TOKEN); } + else if(exception.equals(ErrorCode.WRONG_TYPE_SIGNATURE.getCode())) { + setResponse(response, ErrorCode.WRONG_TYPE_SIGNATURE); + } //토큰 만료된 경우 else if(exception.equals(ErrorCode.EXPIRED_TOKEN.getCode())) { setResponse(response, ErrorCode.EXPIRED_TOKEN); } else { - setResponse(response, ErrorCode.ACCESS_DENIED); + setResponse(response, ErrorCode.TOKEN_NOT_EXIST); } } diff --git a/src/main/java/com/mpnp/baechelin/oauth/filter/TokenAuthenticationFilter.java b/src/main/java/com/mpnp/baechelin/oauth/filter/TokenAuthenticationFilter.java index da0570b..3b5100f 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/filter/TokenAuthenticationFilter.java +++ b/src/main/java/com/mpnp/baechelin/oauth/filter/TokenAuthenticationFilter.java @@ -1,9 +1,13 @@ package com.mpnp.baechelin.oauth.filter; +import com.mpnp.baechelin.oauth.exception.ErrorCode; import com.mpnp.baechelin.oauth.token.AuthToken; import com.mpnp.baechelin.oauth.token.AuthTokenProvider; import com.mpnp.baechelin.util.HeaderUtil; import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.security.SignatureException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; @@ -37,11 +41,27 @@ protected void doFilterInternal( // String으로 된 token을 AuthToken객체로 변환해준다. AuthToken token = tokenProvider.convertAuthToken(tokenStr); - if (token.validate()) { - // 토큰이 유효하다면 인증 객체 생성 - Authentication authentication = tokenProvider.getAuthentication(token); - // SecurityContextHolder 에 인증 객체를 넣는다. - SecurityContextHolder.getContext().setAuthentication(authentication); + try { + if (token != null && token.tokenValidate()) { + Authentication authentication = tokenProvider.getAuthentication(token); + // SecurityContextHolder 에 인증 객체를 넣는다. + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } catch (SignatureException e) { + log.info("잘못된 JWT 서명입니다."); + request.setAttribute("exception", ErrorCode.WRONG_TYPE_SIGNATURE.getCode()); + } catch (MalformedJwtException e) { + log.info("유효하지 않은 구성의 JWT 토큰입니다."); + request.setAttribute("exception", ErrorCode.WRONG_TYPE_TOKEN.getCode()); + } catch (ExpiredJwtException e) { + log.info("만료된 JWT 토큰입니다."); + request.setAttribute("exception", ErrorCode.EXPIRED_TOKEN.getCode()); + } catch (UnsupportedJwtException e) { + log.info("지원되지 않는 형식이나 구성의 JWT 토큰입니다."); + request.setAttribute("exception", ErrorCode.WRONG_TYPE_TOKEN.getCode()); + } catch (IllegalArgumentException e) { + log.info(e.toString().split(":")[1].trim()); + request.setAttribute("exception", ErrorCode.TOKEN_NOT_EXIST.getCode()); } filterChain.doFilter(request, response); diff --git a/src/main/java/com/mpnp/baechelin/oauth/handler/OAuth2AuthenticationSuccessHandler.java b/src/main/java/com/mpnp/baechelin/oauth/handler/OAuth2AuthenticationSuccessHandler.java index 18a182d..84d8c6a 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/handler/OAuth2AuthenticationSuccessHandler.java +++ b/src/main/java/com/mpnp/baechelin/oauth/handler/OAuth2AuthenticationSuccessHandler.java @@ -112,6 +112,7 @@ protected String determineTargetUrl(HttpServletRequest request, HttpServletRespo userRefreshTokenRepository.saveAndFlush(userRefreshToken); } + // 쿠키 만료시간 = 리프레시 토큰 만료시간 int cookieMaxAge = (int) refreshTokenExpiry / 60; // 기존에 cookie에 들어있는 refresh token을 삭제하고 다시 저장한다. diff --git a/src/main/java/com/mpnp/baechelin/oauth/repository/OAuth2AuthorizationRequestBasedOnCookieRepository.java b/src/main/java/com/mpnp/baechelin/oauth/repository/OAuth2AuthorizationRequestBasedOnCookieRepository.java index 64e803e..22c1e2b 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/repository/OAuth2AuthorizationRequestBasedOnCookieRepository.java +++ b/src/main/java/com/mpnp/baechelin/oauth/repository/OAuth2AuthorizationRequestBasedOnCookieRepository.java @@ -15,7 +15,7 @@ public class OAuth2AuthorizationRequestBasedOnCookieRepository implements Author public final static String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request"; public final static String REDIRECT_URI_PARAM_COOKIE_NAME = "redirect_uri"; public final static String REFRESH_TOKEN ="refresh_token"; - private final static int cookieExpireSecondes = 180; + private final static int cookieExpireSeconds = 180; // cookie의 request를 가져오는 로직 @Override @@ -37,11 +37,11 @@ public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationReq return; } - CookieUtil.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CookieUtil.serialize(authorizationRequest), cookieExpireSecondes); + CookieUtil.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CookieUtil.serialize(authorizationRequest), cookieExpireSeconds); String redirectUriAfterLogin = request.getParameter(REDIRECT_URI_PARAM_COOKIE_NAME); if (StringUtils.isNotBlank(redirectUriAfterLogin)) { - CookieUtil.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, cookieExpireSecondes); + CookieUtil.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, cookieExpireSeconds); } } diff --git a/src/main/java/com/mpnp/baechelin/oauth/service/CustomOAuth2UserService.java b/src/main/java/com/mpnp/baechelin/oauth/service/CustomOAuth2UserService.java index 0c04164..bd45331 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/service/CustomOAuth2UserService.java +++ b/src/main/java/com/mpnp/baechelin/oauth/service/CustomOAuth2UserService.java @@ -61,7 +61,7 @@ private OAuth2User process(OAuth2UserRequest userRequest, OAuth2User user) { if (savedUser != null) { // DB에 유저 정보가 있을 때 if (providerType != savedUser.getProviderType()) { - throw new OAuthProviderMissMatchException(ErrorCode.ALREADY_LOGIN_ACCOUNT.getMessage()); + throw new OAuthProviderMissMatchException(ErrorCode.ALREADY_LOGIN_ACCOUNT.getCode() + "=" + providerType); } updateUser(savedUser, userInfo); } else { diff --git a/src/main/java/com/mpnp/baechelin/oauth/token/AuthToken.java b/src/main/java/com/mpnp/baechelin/oauth/token/AuthToken.java index d38af84..8cdbc7e 100644 --- a/src/main/java/com/mpnp/baechelin/oauth/token/AuthToken.java +++ b/src/main/java/com/mpnp/baechelin/oauth/token/AuthToken.java @@ -52,6 +52,15 @@ public boolean validate() { return this.getTokenClaims() != null; } + public boolean tokenValidate() { + Jws claimsJws = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token); + return !claimsJws.getBody().isEmpty(); + } + + // 토큰의 claims, payload 값 가져오기 public Claims getTokenClaims() { try {