From 000ae3e7a8d11064f2197708f05ea2468e8440a6 Mon Sep 17 00:00:00 2001 From: kgy1008 Date: Thu, 11 Jul 2024 06:03:42 +0900 Subject: [PATCH 1/5] [fix] only authenticated by access token --- .../api/auth/service/AuthService.java | 22 ++++++++++-------- .../auth/JwtAuthenticationEntryPoint.java | 14 +++-------- .../auth/filter/JwtAuthenticationFilter.java | 8 +++---- .../hankkiserver/auth/jwt/JwtGenerator.java | 18 ++++++++++----- .../hankkiserver/auth/jwt/JwtProvider.java | 6 ++--- .../hankkiserver/auth/jwt/JwtValidator.java | 23 ++++++++++++------- .../exception/UnauthorizedException.java | 2 -- 7 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/hankki/hankkiserver/api/auth/service/AuthService.java b/src/main/java/org/hankki/hankkiserver/api/auth/service/AuthService.java index c8863d4d..6de9cac5 100644 --- a/src/main/java/org/hankki/hankkiserver/api/auth/service/AuthService.java +++ b/src/main/java/org/hankki/hankkiserver/api/auth/service/AuthService.java @@ -51,12 +51,12 @@ public UserLoginResponse login( return UserLoginResponse.of(issuedToken, isRegistered); } - public void logOut(final long userId) { + public void logOut(final Long userId) { UserInfo findUserInfo = userInfoFinder.getUserInfo(userId); findUserInfo.updateRefreshToken(null); } - public void withdraw(final long userId, final String code) { + public void withdraw(final Long userId, final String code) { User user = userFinder.getUser(userId); if (APPLE == user.getPlatform()){ try { @@ -72,21 +72,26 @@ public void withdraw(final long userId, final String code) { @Transactional(noRollbackFor = UnauthorizedException.class) public UserReissueResponse reissue(final String refreshToken) { - long userId = jwtProvider.getSubject(refreshToken.substring(BEARER.length())); + Long userId = jwtProvider.getSubject(refreshToken.substring(BEARER.length())); validateRefreshToken(refreshToken, userId); UserInfo findUserInfo = userInfoFinder.getUserInfo(userId); - Token issuedTokens = jwtProvider.issueTokens(userId); + Token issuedTokens = jwtProvider.issueTokens(userId, getUserRole(userId)); findUserInfo.updateRefreshToken(issuedTokens.refreshToken()); return UserReissueResponse.of(issuedTokens); } - private Token generateTokens(final long userId) { - Token issuedTokens = jwtProvider.issueTokens(userId); + private Token generateTokens(final Long userId) { + String role = userFinder.getUser(userId).getUserRole().getValue(); + Token issuedTokens = jwtProvider.issueTokens(userId, getUserRole(userId)); UserInfo findUserInfo = userInfoFinder.getUserInfo(userId); findUserInfo.updateRefreshToken(issuedTokens.refreshToken()); return issuedTokens; } + private String getUserRole(Long userId) { + return userFinder.getUser(userId).getUserRole().getValue(); + } + private SocialInfoDto getSocialInfo( final String providerToken, final Platform platform, @@ -119,8 +124,7 @@ private User updateUserInfo(final User user) { } private String getRefreshToken(final Long userId) { - return userInfoFinder.getUserInfo(userId) - .getRefreshToken(); + return userInfoFinder.getUserInfo(userId).getRefreshToken(); } private void saveUserAndUserInfo(final User user) { @@ -129,7 +133,7 @@ private void saveUserAndUserInfo(final User user) { userInfoSaver.saveUserInfo(userInfo); } - private void validateRefreshToken(final String refreshToken, final long userId) { + private void validateRefreshToken(final String refreshToken, final Long userId) { try { jwtValidator.validateRefreshToken(refreshToken); String storedRefreshToken = getRefreshToken(userId); diff --git a/src/main/java/org/hankki/hankkiserver/auth/JwtAuthenticationEntryPoint.java b/src/main/java/org/hankki/hankkiserver/auth/JwtAuthenticationEntryPoint.java index 2460af36..ee42b4ce 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/JwtAuthenticationEntryPoint.java +++ b/src/main/java/org/hankki/hankkiserver/auth/JwtAuthenticationEntryPoint.java @@ -12,7 +12,6 @@ import org.springframework.stereotype.Component; import java.io.IOException; -import java.io.PrintWriter; @Component public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { @@ -20,10 +19,7 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { private final ObjectMapper objectMapper = new ObjectMapper(); @Override - public void commence( - HttpServletRequest request, - HttpServletResponse response, - AuthenticationException authException) throws IOException { + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { handleException(response); } @@ -31,14 +27,10 @@ private void handleException(HttpServletResponse response) throws IOException { setResponse(response, HttpStatus.UNAUTHORIZED, AuthErrorCode.UNAUTHORIZED); } - private void setResponse( - HttpServletResponse response, - HttpStatus httpStatus, - AuthErrorCode authErrorCode) throws IOException { + private void setResponse(HttpServletResponse response, HttpStatus httpStatus, AuthErrorCode authErrorCode) throws IOException { response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("utf-8"); response.setStatus(httpStatus.value()); - PrintWriter writer = response.getWriter(); - writer.write(objectMapper.writeValueAsString(HankkiResponse.fail(authErrorCode))); + response.getWriter().write(objectMapper.writeValueAsString(HankkiResponse.fail(authErrorCode))); } } diff --git a/src/main/java/org/hankki/hankkiserver/auth/filter/JwtAuthenticationFilter.java b/src/main/java/org/hankki/hankkiserver/auth/filter/JwtAuthenticationFilter.java index fd6514ed..a1197833 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/filter/JwtAuthenticationFilter.java +++ b/src/main/java/org/hankki/hankkiserver/auth/filter/JwtAuthenticationFilter.java @@ -9,6 +9,7 @@ import org.hankki.hankkiserver.auth.jwt.JwtProvider; import org.hankki.hankkiserver.auth.jwt.JwtValidator; import org.hankki.hankkiserver.common.code.AuthErrorCode; +import org.hankki.hankkiserver.common.code.ErrorCode; import org.hankki.hankkiserver.common.exception.UnauthorizedException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; @@ -29,12 +30,9 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtProvider jwtProvider; @Override - protected void doFilterInternal( - HttpServletRequest request, - HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { final String accessToken = getAccessToken(request); - jwtValidator.validateAccessToken(accessToken); + jwtValidator.validateAccessToken(accessToken, request.getRequestURI()); doAuthentication(request, jwtProvider.getSubject(accessToken)); filterChain.doFilter(request, response); } diff --git a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtGenerator.java b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtGenerator.java index ed807c16..a5abcfc8 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtGenerator.java +++ b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtGenerator.java @@ -1,9 +1,7 @@ package org.hankki.hankkiserver.auth.jwt; -import io.jsonwebtoken.Header; -import io.jsonwebtoken.JwtParser; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.*; +import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -22,12 +20,20 @@ public class JwtGenerator { @Value("${jwt.refresh-token-expiration}") private long REFRESH_TOKEN_EXPIRE_TIME; - public String generateToken(Long userId, boolean isAccessToken) { + public static final String USER_ROLE_CLAIM_NAME = "role"; + + public String generateToken(Long userId, String role, boolean isAccessToken) { final Date now = generateNowDate(); final Date expiration = generateExpirationDate(isAccessToken, now); + + Claims claims = Jwts.claims().setSubject(String.valueOf(userId)); + if (isAccessToken) { + claims.put(USER_ROLE_CLAIM_NAME, role); + } + return Jwts.builder() .setHeaderParam(Header.TYPE, Header.JWT_TYPE) - .setSubject(String.valueOf(userId)) + .setClaims(claims) .setIssuedAt(now) .setExpiration(expiration) .signWith(getSigningKey(), SignatureAlgorithm.HS256) diff --git a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtProvider.java b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtProvider.java index c304eba0..ee85790c 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtProvider.java +++ b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtProvider.java @@ -10,9 +10,9 @@ public class JwtProvider { private final JwtGenerator jwtGenerator; - public Token issueTokens(Long userId) { - return Token.of(jwtGenerator.generateToken(userId, true), - jwtGenerator.generateToken(userId, false)); + public Token issueTokens(Long userId, String role) { + return Token.of(jwtGenerator.generateToken(userId, role, true), + jwtGenerator.generateToken(userId, role, false)); } public Long getSubject(String token) { diff --git a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java index 62048988..a4f9140e 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java +++ b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java @@ -1,12 +1,14 @@ package org.hankki.hankkiserver.auth.jwt; +import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.JwtParser; import lombok.RequiredArgsConstructor; import org.hankki.hankkiserver.common.code.AuthErrorCode; import org.hankki.hankkiserver.common.exception.UnauthorizedException; import org.springframework.stereotype.Component; +import java.net.URI; + import static org.hankki.hankkiserver.auth.filter.JwtAuthenticationFilter.BEARER; @RequiredArgsConstructor @@ -15,9 +17,14 @@ public class JwtValidator { private final JwtGenerator jwtGenerator; - public void validateAccessToken(String accessToken) { + public void validateAccessToken(String accessToken, String requestURI) { try { - parseToken(accessToken); + String role = parseToken(accessToken).get(JwtGenerator.USER_ROLE_CLAIM_NAME, String.class); + if (role == null) { + if (!requestURI.equals("/api/v1/auth/reissue")) { + throw new UnauthorizedException(AuthErrorCode.INVALID_ACCESS_TOKEN_VALUE); + } + } } catch (ExpiredJwtException e) { throw new UnauthorizedException(AuthErrorCode.EXPIRED_ACCESS_TOKEN); } catch (Exception e) { @@ -27,6 +34,7 @@ public void validateAccessToken(String accessToken) { public void validateRefreshToken(final String refreshToken) { try { + System.out.println("refreshToken" + refreshToken); parseToken(getToken(refreshToken)); } catch (ExpiredJwtException e) { throw new UnauthorizedException(AuthErrorCode.EXPIRED_REFRESH_TOKEN); @@ -43,15 +51,14 @@ public void equalsRefreshToken( } } - private void parseToken(String token) { - JwtParser jwtParser = jwtGenerator.getJwtParser(); - jwtParser.parseClaimsJws(token); - } - private String getToken(final String refreshToken) { if (refreshToken.startsWith(BEARER)) { return refreshToken.substring(BEARER.length()); } throw new UnauthorizedException(AuthErrorCode.MISSING_BEARER_PREFIX); } + + private Claims parseToken(final String token) { + return jwtGenerator.getJwtParser().parseClaimsJws(token).getBody(); + } } diff --git a/src/main/java/org/hankki/hankkiserver/common/exception/UnauthorizedException.java b/src/main/java/org/hankki/hankkiserver/common/exception/UnauthorizedException.java index f86efcd7..48dc1cf1 100644 --- a/src/main/java/org/hankki/hankkiserver/common/exception/UnauthorizedException.java +++ b/src/main/java/org/hankki/hankkiserver/common/exception/UnauthorizedException.java @@ -1,7 +1,6 @@ package org.hankki.hankkiserver.common.exception; import lombok.Getter; -import org.hankki.hankkiserver.common.code.AuthErrorCode; import org.hankki.hankkiserver.common.code.ErrorCode; @Getter @@ -12,6 +11,5 @@ public UnauthorizedException(ErrorCode errorCode) { super(errorCode.getMessage()); this.errorCode = errorCode; } - } From b2795987c36e421b0c62eb072503e53fed7feb7c Mon Sep 17 00:00:00 2001 From: kgy1008 Date: Thu, 11 Jul 2024 06:43:14 +0900 Subject: [PATCH 2/5] [fix] fix encoding method for secret key --- server-yml | 2 +- .../org/hankki/hankkiserver/auth/jwt/JwtGenerator.java | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/server-yml b/server-yml index 81b4fcff..6bf35196 160000 --- a/server-yml +++ b/server-yml @@ -1 +1 @@ -Subproject commit 81b4fcff1239b8e28c295477a0ff6cbf33e5b976 +Subproject commit 6bf351960cedb83a36dd2a9d986c75ef99475544 diff --git a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtGenerator.java b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtGenerator.java index a5abcfc8..9f760f56 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtGenerator.java +++ b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtGenerator.java @@ -1,7 +1,6 @@ package org.hankki.hankkiserver.auth.jwt; import io.jsonwebtoken.*; -import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -55,7 +54,8 @@ private Date generateExpirationDate(boolean isAccessToken, Date now) { } private Key getSigningKey() { - return Keys.hmacShaKeyFor(encodeSecretKey().getBytes()); + byte[] keyBytes = Base64.getDecoder().decode(JWT_SECRET); + return Keys.hmacShaKeyFor(keyBytes); } private long calculateExpirationTime(boolean isAccessToken) { @@ -64,10 +64,4 @@ private long calculateExpirationTime(boolean isAccessToken) { } return REFRESH_TOKEN_EXPIRE_TIME; } - - private String encodeSecretKey() { - return Base64.getEncoder() - .encodeToString(JWT_SECRET.getBytes()); - } } - From ffc83ba7c2faba6a277c1c8af0b17e1de2e9dd12 Mon Sep 17 00:00:00 2001 From: kgy1008 Date: Thu, 11 Jul 2024 14:08:25 +0900 Subject: [PATCH 3/5] [refac] delete unnecessary code --- .../java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java index a4f9140e..9c3e3dde 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java +++ b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java @@ -21,9 +21,7 @@ public void validateAccessToken(String accessToken, String requestURI) { try { String role = parseToken(accessToken).get(JwtGenerator.USER_ROLE_CLAIM_NAME, String.class); if (role == null) { - if (!requestURI.equals("/api/v1/auth/reissue")) { - throw new UnauthorizedException(AuthErrorCode.INVALID_ACCESS_TOKEN_VALUE); - } + throw new UnauthorizedException(AuthErrorCode.INVALID_ACCESS_TOKEN_VALUE); } } catch (ExpiredJwtException e) { throw new UnauthorizedException(AuthErrorCode.EXPIRED_ACCESS_TOKEN); From 39deeb4148fdbddf3480029b7b230db93a452dd4 Mon Sep 17 00:00:00 2001 From: kgy1008 Date: Thu, 11 Jul 2024 14:32:32 +0900 Subject: [PATCH 4/5] [refac] delete unnecessary code --- .../hankkiserver/auth/filter/JwtAuthenticationFilter.java | 2 +- .../java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/hankki/hankkiserver/auth/filter/JwtAuthenticationFilter.java b/src/main/java/org/hankki/hankkiserver/auth/filter/JwtAuthenticationFilter.java index a1197833..5f244df6 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/filter/JwtAuthenticationFilter.java +++ b/src/main/java/org/hankki/hankkiserver/auth/filter/JwtAuthenticationFilter.java @@ -32,7 +32,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { final String accessToken = getAccessToken(request); - jwtValidator.validateAccessToken(accessToken, request.getRequestURI()); + jwtValidator.validateAccessToken(accessToken); doAuthentication(request, jwtProvider.getSubject(accessToken)); filterChain.doFilter(request, response); } diff --git a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java index 9c3e3dde..e912d6e1 100644 --- a/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java +++ b/src/main/java/org/hankki/hankkiserver/auth/jwt/JwtValidator.java @@ -17,7 +17,7 @@ public class JwtValidator { private final JwtGenerator jwtGenerator; - public void validateAccessToken(String accessToken, String requestURI) { + public void validateAccessToken(String accessToken) { try { String role = parseToken(accessToken).get(JwtGenerator.USER_ROLE_CLAIM_NAME, String.class); if (role == null) { From ae1c7ab6b93620b9af26ad978a7d1b2ec4baabbc Mon Sep 17 00:00:00 2001 From: kgy1008 Date: Thu, 11 Jul 2024 16:09:02 +0900 Subject: [PATCH 5/5] [chore] update yml --- server-yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server-yml b/server-yml index 6bf35196..fdc9b7c3 160000 --- a/server-yml +++ b/server-yml @@ -1 +1 @@ -Subproject commit 6bf351960cedb83a36dd2a9d986c75ef99475544 +Subproject commit fdc9b7c32fcedbcfdc45cd6b327fdb92c75ebf1e