-
Notifications
You must be signed in to change notification settings - Fork 0
π Jwt Refresh #36
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
π Jwt Refresh #36
Changes from 2 commits
d34abc3
49b9c5f
7341b5b
2a4d71e
ed35dc5
230cb35
c63c7ff
608a2e9
d2e5305
f16eaec
c25e10d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package com.mycom.socket.auth.controller; | ||
|
|
||
| import com.mycom.socket.auth.config.JWTProperties; | ||
| import com.mycom.socket.auth.dto.response.TokenResponse; | ||
| import com.mycom.socket.auth.jwt.JWTUtil; | ||
| import com.mycom.socket.auth.security.CookieUtil; | ||
| import com.mycom.socket.global.exception.BadRequestException; | ||
| import io.jsonwebtoken.JwtException; | ||
| import jakarta.servlet.http.Cookie; | ||
| import jakarta.servlet.http.HttpServletRequest; | ||
| import jakarta.servlet.http.HttpServletResponse; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| @RestController | ||
| @RequiredArgsConstructor | ||
| public class RefreshController { | ||
|
|
||
| private final JWTUtil jwtUtil; | ||
| private final CookieUtil cookieUtil; | ||
| private final JWTProperties jwtProperties; | ||
|
|
||
| @PostMapping("/refresh") | ||
| public TokenResponse refreshAccessToken(HttpServletRequest request, HttpServletResponse response) { | ||
| String refreshToken = extractRefreshToken(request); | ||
|
|
||
| try { | ||
| jwtUtil.validateToken(refreshToken); | ||
| } catch (JwtException e) { | ||
| response.addCookie(cookieUtil.createExpiredRefreshCookie()); | ||
| throw new BadRequestException("μ ν¨νμ§ μμ 리νλ μ ν ν°μ λλ€. λ€μ λ‘κ·ΈμΈν΄μ£ΌμΈμ."); | ||
| } | ||
|
|
||
| String email = jwtUtil.getEmail(refreshToken); | ||
| String newAccessToken = jwtUtil.createToken(email, jwtProperties.getAccessTokenValidityInSeconds()); | ||
|
|
||
| Cookie accessTokenCookie = cookieUtil.createAuthCookie(newAccessToken); | ||
| response.addCookie(accessTokenCookie); | ||
|
|
||
| String newRefreshToken = jwtUtil.createToken(email, jwtProperties.getRefreshTokenValidityInSeconds()); | ||
| Cookie refreshTokenCookie = cookieUtil.createRefreshCookie(newRefreshToken); | ||
| response.addCookie(refreshTokenCookie); | ||
|
|
||
|
Comment on lines
+41
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π‘ Codebase verification ν ν° κ΄λ¦¬ 보μ μ·¨μ½μ νμΈλ¨ νμ¬ κ΅¬νμμ λ€μκ³Ό κ°μ 보μ μ·¨μ½μ μ΄ λ°κ²¬λμμ΅λλ€:
κΆμ₯ μ¬ν:
π Analysis chainν ν° μ¬λ°κΈ λ‘μ§ κ²μ¦ νμ μλ‘μ΄ ν ν° λ°κΈ μ λ€μ μ¬νλ€μ νμΈν΄μΌ ν©λλ€:
π Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Check for token revocation implementation
rg -l "TokenRevocationService|BlacklistService|InvalidatedTokenRepository"
Length of output: 76 Script: #!/bin/bash
# Search for token-related implementations with broader patterns
rg -l "token.*repository|token.*service|token.*cache|token.*store"
# Search for security configurations
rg -l "SecurityConfig|WebSecurityConfig|JwtConfig"
# Search for Redis or cache configurations
rg -l "RedisConfig|CacheConfig|TokenCache"
Length of output: 364 Script: #!/bin/bash
# Check Redis configuration implementation
cat src/main/java/com/mycom/socket/global/config/RedisConfig.java
# Check security configuration for token handling
cat src/main/java/com/mycom/socket/auth/config/SecurityConfig.java
# Search for Redis usage in token operations
rg -g "!*.{test,spec}.*" "redisTemplate|StringRedisTemplate" -A 3
Length of output: 7750 |
||
| return TokenResponse.of(newAccessToken); | ||
| } | ||
|
Comment on lines
+27
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 보μ κ°μ μ΄ νμν©λλ€. λ€μ 보μ κ΄λ ¨ μ¬νλ€μ κ³ λ €ν΄μ£ΌμΈμ:
λ€μκ³Ό κ°μ΄ rate limitingμ μΆκ°νλ κ²μ μ μν©λλ€: + @RateLimiter(name = "refreshToken", fallbackMethod = "refreshTokenFallback")
@PostMapping("/refresh")
public TokenResponse refreshAccessToken(...)κ·Έλ¦¬κ³ μ€ν¨ν μλμ λν λ‘κΉ μ μΆκ°νμΈμ: } catch (JwtException e) {
+ log.warn("Failed refresh token attempt for IP: {}", request.getRemoteAddr());
response.addCookie(cookieUtil.createExpiredCookie(jwtProperties.getRefreshTokenCookieName()));
throw new BadRequestException("μ ν¨νμ§ μμ 리νλ μ ν ν°μ
λλ€. λ€μ λ‘κ·ΈμΈν΄μ£ΌμΈμ.");
}
|
||
|
|
||
| private String extractRefreshToken(HttpServletRequest request) { | ||
| if (request.getCookies() == null) { | ||
| throw new BadRequestException("리νλ μ ν ν°μ΄ μμ΅λλ€. λ€μ λ‘κ·ΈμΈν΄μ£ΌμΈμ."); | ||
| } | ||
|
|
||
| for (Cookie cookie : request.getCookies()) { | ||
| if (jwtProperties.getRefreshTokenCookieName().equals(cookie.getName())) { | ||
| return cookie.getValue(); | ||
| } | ||
| } | ||
| throw new BadRequestException("리νλ μ ν ν°μ΄ μμ΅λλ€. λ€μ λ‘κ·ΈμΈν΄μ£ΌμΈμ."); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.mycom.socket.auth.dto.response; | ||
|
|
||
| public record TokenResponse( | ||
| String accessToken | ||
| ) { | ||
| public static TokenResponse of(String accessToken) { | ||
| return new TokenResponse(accessToken); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,13 +25,26 @@ public JWTUtil(JWTProperties jwtProperties) { | |
| ); | ||
| } | ||
|
|
||
| /** | ||
| * μ‘μΈμ€ ν ν° μμ± | ||
| */ | ||
| public String createAccessToken(String email) { | ||
| return createToken(email, jwtProperties.getAccessTokenValidityInSeconds()); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ν ν° νμ ꡬλΆμ μν claim μΆκ° νμ μ‘μΈμ€ ν ν°κ³Ό 리νλ μ ν ν°μ ꡬλΆν μ μλ claimμ΄ μμ΄ ν ν° μ νμ νμΈν μ μμ΅λλ€. λ€μκ³Ό κ°μ΄ μμ νλ κ²μ μ μν©λλ€: public String createAccessToken(String email) {
- return createToken(email, jwtProperties.getAccessTokenValidityInSeconds());
+ return createToken(email, "ACCESS", jwtProperties.getAccessTokenValidityInSeconds());
}
public String createRefreshToken(String email) {
- return createToken(email, jwtProperties.getRefreshTokenValidityInSeconds());
+ return createToken(email, "REFRESH", jwtProperties.getRefreshTokenValidityInSeconds());
}Also applies to: 38-40 |
||
|
|
||
| /** | ||
| * 리νλ μ ν ν° μμ± | ||
| */ | ||
| public String createRefreshToken(String email) { | ||
| return createToken(email, jwtProperties.getRefreshTokenValidityInSeconds()); | ||
| } | ||
|
|
||
| /** | ||
| * JWT ν ν° μμ± | ||
| */ | ||
| public String createToken(String email) { | ||
| public String createToken(String email, long validityInSeconds) { | ||
| Date now = new Date(); | ||
| Date validity = new Date(now.getTime() + | ||
| (jwtProperties.getAccessTokenValidityInSeconds() * 1000)); | ||
| Date validity = new Date(now.getTime() + (validityInSeconds * 1000)); | ||
|
|
||
| return Jwts.builder() | ||
| .issuer(jwtProperties.getIssuer()) | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -14,19 +14,44 @@ public class CookieUtil { | |||||||||||||||||||||||||||||||||||||||
| * μΈμ¦ μΏ ν€ μμ± | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| public Cookie createAuthCookie(String token) { | ||||||||||||||||||||||||||||||||||||||||
| Cookie cookie = new Cookie(jwtProperties.getCookieName(), token); | ||||||||||||||||||||||||||||||||||||||||
| Cookie cookie = new Cookie(jwtProperties.getAccessTokenCookieName(), token); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setHttpOnly(true); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setSecure(jwtProperties.isSecureCookie()); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setPath("/"); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setMaxAge((int) jwtProperties.getAccessTokenValidityInSeconds()); | ||||||||||||||||||||||||||||||||||||||||
| return cookie; | ||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion μΏ ν€ μμ± λ‘μ§ μ€λ³΅ μ κ±° νμ μΈμ¦ μΏ ν€μ 리νλ μ μΏ ν€ μμ± λ‘μ§μ΄ μ€λ³΅λμ΄ μμ΅λλ€. κ³΅ν΅ λ©μλλ‘ μΆμΆνλ©΄ μ½λ μ μ§λ³΄μκ° λ μ¬μμ§ κ² κ°μ΅λλ€. λ€μκ³Ό κ°μ΄ μμ νλ κ²μ μ μν©λλ€: + private Cookie createCookie(String name, String value, long maxAgeInSeconds) {
+ Cookie cookie = new Cookie(name, value);
+ cookie.setHttpOnly(true);
+ cookie.setSecure(jwtProperties.isSecureCookie());
+ cookie.setPath("/");
+ cookie.setMaxAge((int) maxAgeInSeconds);
+ return cookie;
+ }
public Cookie createAuthCookie(String token) {
- Cookie cookie = new Cookie(jwtProperties.getAccessTokenCookieName(), token);
- cookie.setHttpOnly(true);
- cookie.setSecure(jwtProperties.isSecureCookie());
- cookie.setPath("/");
- cookie.setMaxAge((int) jwtProperties.getAccessTokenValidityInSeconds());
- return cookie;
+ return createCookie(
+ jwtProperties.getAccessTokenCookieName(),
+ token,
+ jwtProperties.getAccessTokenValidityInSeconds()
+ );
}
public Cookie createRefreshCookie(String token) {
- Cookie cookie = new Cookie(jwtProperties.getRefreshTokenCookieName(), token);
- cookie.setHttpOnly(true);
- cookie.setSecure(jwtProperties.isSecureCookie());
- cookie.setPath("/");
- cookie.setMaxAge((int) jwtProperties.getRefreshTokenValidityInSeconds());
- return cookie;
+ return createCookie(
+ jwtProperties.getRefreshTokenCookieName(),
+ token,
+ jwtProperties.getRefreshTokenValidityInSeconds()
+ );
}Also applies to: 29-34 |
||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion 보μ κ°νλ₯Ό μν SameSite μμ± μΆκ° νμ μΏ ν€ μμ± μ CSRF 곡격 λ°©μ§λ₯Ό μν΄ SameSite μμ±μ μΆκ°νλ κ²μ΄ μ’μ΅λλ€. private Cookie createCookie(String name, String value, long maxAge, boolean secure) {
Cookie cookie = new Cookie(name, value);
cookie.setHttpOnly(true);
cookie.setSecure(secure);
cookie.setPath("/");
cookie.setMaxAge((int) maxAge);
+ cookie.setAttribute("SameSite", "Strict");
return cookie;
}π Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * 리νλ μ ν ν° μΏ ν€ μμ± | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| public Cookie createRefreshCookie(String token) { | ||||||||||||||||||||||||||||||||||||||||
| Cookie cookie = new Cookie(jwtProperties.getRefreshTokenCookieName(), token); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setHttpOnly(true); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setSecure(jwtProperties.isSecureCookie()); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setPath("/"); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setMaxAge((int) jwtProperties.getRefreshTokenValidityInSeconds()); | ||||||||||||||||||||||||||||||||||||||||
| return cookie; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * μΈμ¦ μΏ ν€ λ§λ£ μ²λ¦¬ | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| public Cookie createExpiredAuthCookie() { | ||||||||||||||||||||||||||||||||||||||||
| Cookie cookie = new Cookie(jwtProperties.getCookieName(), null); | ||||||||||||||||||||||||||||||||||||||||
| Cookie cookie = new Cookie(jwtProperties.getAccessTokenCookieName(), null); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setHttpOnly(true); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setSecure(true); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setPath("/"); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setMaxAge(0); // μ¦μ λ§λ£ | ||||||||||||||||||||||||||||||||||||||||
| return cookie; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion λ§λ£λ μΏ ν€ μμ± λ‘μ§ μ€λ³΅ μ κ±° λ° λ³΄μ μ€μ κ°ν νμ λ§λ£λ μΏ ν€ μμ± λ‘μ§λ μ€λ³΅λμ΄ μμΌλ©°, SameSite μμ± μ€μ μ΄ λλ½λμ΄ μμ΅λλ€. λ€μκ³Ό κ°μ΄ μμ νλ κ²μ μ μν©λλ€: + private Cookie createExpiredCookie(String name) {
+ Cookie cookie = new Cookie(name, null);
+ cookie.setHttpOnly(true);
+ cookie.setSecure(true);
+ cookie.setPath("/");
+ cookie.setMaxAge(0);
+ cookie.setAttribute("SameSite", "Strict");
+ return cookie;
+ }
public Cookie createExpiredAuthCookie() {
- Cookie cookie = new Cookie(jwtProperties.getAccessTokenCookieName(), null);
- cookie.setHttpOnly(true);
- cookie.setSecure(true);
- cookie.setPath("/");
- cookie.setMaxAge(0);
- return cookie;
+ return createExpiredCookie(jwtProperties.getAccessTokenCookieName());
}
public Cookie createExpiredRefreshCookie() {
- Cookie cookie = new Cookie(jwtProperties.getRefreshTokenCookieName(), null);
- cookie.setHttpOnly(true);
- cookie.setSecure(true);
- cookie.setPath("/");
- cookie.setMaxAge(0);
- return cookie;
+ return createExpiredCookie(jwtProperties.getRefreshTokenCookieName());
}Also applies to: 54-59
Comment on lines
+49
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π‘ Codebase verification ν ν° μ ν¨κΈ°κ° κ²μ¦ λ‘μ§ κ΅¬ν λ°©μ 리νλ μ ν ν°μ μ ν¨ κΈ°κ°μ΄ μ‘μΈμ€ ν ν°λ³΄λ€ κΈΈλλ‘ λ³΄μ₯νκΈ° μν΄ λ€μκ³Ό κ°μ κ²μ¦ λ‘μ§ μΆκ°λ₯Ό μ μλ립λλ€:
π Analysis chain리νλ μ ν ν° μ ν¨ κΈ°κ° κ²μ¦ μΆκ° κ³ λ € 리νλ μ ν ν°μ μ ν¨ κΈ°κ°μ΄ μ‘μΈμ€ ν ν°λ³΄λ€ κΈΈκ² μ€μ λμλμ§ νμΈνλ κ²μ¦ λ‘μ§ μΆκ°λ₯Ό κ³ λ €ν΄λ³΄μΈμ. π Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# JWTPropertiesμμ ν ν° μ ν¨ κΈ°κ° μ€μ μ νμΈ
rg "tokenValidityInSeconds|refreshTokenValidityInSeconds" -A 2
Length of output: 383 Script: #!/bin/bash
# Get complete JWTProperties class
cat src/main/java/com/mycom/socket/auth/config/JWTProperties.java
# Check application properties/yaml files
fd -e yml -e yaml -e properties --exec cat {}
Length of output: 1162 |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * 리νλ μ ν ν° μΏ ν€ λ§λ£ μ²λ¦¬ | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
| public Cookie createExpiredRefreshCookie() { | ||||||||||||||||||||||||||||||||||||||||
| Cookie cookie = new Cookie(jwtProperties.getRefreshTokenCookieName(), null); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setHttpOnly(true); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setSecure(true); | ||||||||||||||||||||||||||||||||||||||||
| cookie.setPath("/"); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,11 +51,14 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR | |
| MemberDetails memberDetails = (MemberDetails) authResult.getPrincipal(); | ||
| Member member = memberDetails.getMember(); | ||
|
|
||
| String token = jwtUtil.createToken(member.getEmail()); | ||
| String accessToken = jwtUtil.createAccessToken(member.getEmail()); //μ‘μΈμ€ ν ν° μμ± | ||
| String refreshToken = jwtUtil.createRefreshToken(member.getEmail()); //리νλ μ ν ν° μμ± | ||
|
|
||
| // μΏ ν€ μμ± λ° μ€μ | ||
| Cookie authCookie = cookieUtil.createAuthCookie(token); | ||
| response.addCookie(authCookie); | ||
| Cookie accessTokenCookie = cookieUtil.createAuthCookie(accessToken); //μ‘μΈμ€ ν ν° μΏ ν€ | ||
| Cookie refreshTokenCookie = cookieUtil.createRefreshCookie(refreshToken); //리νλ μ ν ν° μΏ ν€ | ||
| response.addCookie(accessTokenCookie); | ||
| response.addCookie(refreshTokenCookie); | ||
|
Comment on lines
+69
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π‘ Codebase verification μΏ ν€ λ³΄μ μ€μ μ΄ λΆμμ ν©λλ€. λ€μκ³Ό κ°μ 보μ λ¬Έμ κ° λ°κ²¬λμμ΅λλ€:
μμ μ΄ νμν νμΌ:
κΆμ₯ μ¬ν:
π Analysis chainμΏ ν€ λ³΄μ μ€μ μ νμΈν΄μ£ΌμΈμ. μΏ ν€ μμ± μ λ€μ 보μ μμ±λ€μ΄ μ¬λ°λ₯΄κ² μ€μ λμ΄ μλμ§ νμΈμ΄ νμν©λλ€:
π Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# CookieUtilμ ꡬνμ νμΈνμ¬ λ³΄μ μ€μ κ²μ¦
rg -A 10 "createAuthCookie|createRefreshCookie" --type java
Length of output: 8548 Script: #!/bin/bash
# Check createCookie implementation and JwtProperties
echo "=== CookieUtil.createCookie implementation ==="
ast-grep --pattern 'createCookie($$$) { $$$ }'
echo -e "\n=== JwtProperties configuration ==="
rg -A 5 "class JwtProperties" --type java
Length of output: 282 Script: #!/bin/bash
# μΏ ν€ μμ± λ©μλμ μ€μ νμΌ κ²μ
echo "=== Cookie creation implementation ==="
rg -A 15 "private.*createCookie" --type java
echo -e "\n=== Security and JWT configuration ==="
fd -e yml -e properties -e yaml | xargs rg -l "jwt|cookie|secure"
Length of output: 1755 |
||
|
|
||
| // λ‘κ·ΈμΈ μλ΅ μμ± | ||
| LoginResponse loginResponse = new LoginResponse(member.getEmail(), member.getNickname()); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package com.mycom.socket.auth.service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.mycom.socket.auth.config.JWTProperties; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.mycom.socket.auth.dto.response.RegisterResponse; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.mycom.socket.auth.jwt.JWTUtil; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.mycom.socket.auth.security.CookieUtil; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -28,6 +29,7 @@ public class AuthService { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final JWTUtil jwtUtil; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final MailService mailService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final CookieUtil cookieUtil; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final JWTProperties jwtProperties; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * μ¬μ©μ λ‘κ·ΈμΈ μ²λ¦¬ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -46,8 +48,17 @@ public LoginResponse login(LoginRequest request, HttpServletResponse response) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new BadRequestException("μλͺ»λ λΉλ°λ²νΈμ λλ€."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String token = jwtUtil.createToken(member.getEmail()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response.addCookie(cookieUtil.createAuthCookie(token)); // CookieUtil μ¬μ© | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String refreshToken = jwtUtil.createToken(member.getEmail(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jwtProperties.getRefreshTokenValidityInSeconds()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Cookie refreshTokenCookie = cookieUtil.createRefreshCookie(refreshToken); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response.addCookie(refreshTokenCookie); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String accessToken = jwtUtil.createToken(member.getEmail(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jwtProperties.getAccessTokenValidityInSeconds()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Cookie accessTokenCookie = cookieUtil.createAuthCookie(accessToken); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response.addCookie(accessTokenCookie); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+51
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μ¬κ°ν ν ν° μμ± λ‘μ§ μ€λ₯κ° λ°κ²¬λμμ΅λλ€. λ€μκ³Ό κ°μ μΉλͺ μ μΈ λ¬Έμ μ λ€μ΄ μμ΅λλ€:
λ€μκ³Ό κ°μ΄ μμ ν΄μ£ΌμΈμ: - // λ¨Όμ μ‘μΈμ€ ν ν° μμ±
- String accessToken = jwtUtil.createToken(member.getEmail(),
- jwtProperties.getRefreshTokenValidityInSeconds(), "ACCESS_TOKEN");
-
- Cookie refreshTokenCookie = cookieUtil.createRefreshCookie(accessToken);
-
- // κ·Έ λ€μ 리νλ μ ν ν° μμ±
- String refreshToken = jwtUtil.createToken(member.getEmail(),
- jwtProperties.getAccessTokenValidityInSeconds(), "REFRESH_TOKEN");
-
- Cookie accessTokenCookie = cookieUtil.createAuthCookie(refreshToken);
-
- // μΏ ν€ μ€μ
- response.addCookie(refreshTokenCookie);
- response.addCookie(accessTokenCookie);
+ // μ‘μΈμ€ ν ν° μμ±
+ String accessToken = jwtUtil.createToken(member.getEmail(),
+ jwtProperties.getAccessTokenValidityInSeconds(), "ACCESS_TOKEN");
+ Cookie accessTokenCookie = cookieUtil.createAuthCookie(accessToken);
+
+ // 리νλ μ ν ν° μμ±
+ String refreshToken = jwtUtil.createToken(member.getEmail(),
+ jwtProperties.getRefreshTokenValidityInSeconds(), "REFRESH_TOKEN");
+ Cookie refreshTokenCookie = cookieUtil.createRefreshCookie(refreshToken);
+
+ // μΏ ν€ μ€μ
+ response.addCookie(accessTokenCookie);
+ response.addCookie(refreshTokenCookie);π Committable suggestion
Suggested change
π‘ Codebase verification π οΈ Refactor suggestion 리νλ μ ν ν° λ³΄μ μ·¨μ½μ μ΄ νμΈλμμ΅λλ€. νμ¬ κ΅¬νμμ λ€μκ³Ό κ°μ 보μ μ·¨μ½μ μ΄ λ°κ²¬λμμ΅λλ€:
λ€μ 보μ κΈ°λ₯μ μΆκ°λ₯Ό κΆμ₯λ립λλ€:
π Analysis chain리νλ μ ν ν° λ³΄μ κ°νκ° νμν©λλ€. 리νλ μ ν ν°μ 보μμ κ°ννκΈ° μν΄ λ€μ κΈ°λ₯λ€μ ꡬνμ κ³ λ €ν΄μ£ΌμΈμ:
리νλ μ ν ν° κ΅¬νμ΄ μ μ νμ§ νμΈνκΈ° μν΄ λ€μ κ²μ¦μ μ€νν©λλ€: π Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Verify refresh token implementation completeness
# Check for token rotation implementation
echo "Checking for token rotation..."
rg -l 'refreshToken.*rotation|rotateRefreshToken|updateRefreshToken'
# Check for token reuse detection
echo "Checking for reuse detection..."
rg -l 'tokenReuse|detectReuse|validateRefreshToken'
# Check for proper token validation
echo "Checking for token validation..."
rg -l 'validateToken|verifyToken|checkToken'
Length of output: 628 Script: #!/bin/bash
# Check the actual implementation details
echo "=== Member.java refresh token handling ==="
rg -A 10 -B 10 'refreshToken' src/main/java/com/mycom/socket/go_socket/entity/Member.java
echo -e "\n=== RefreshController implementation ==="
cat src/main/java/com/mycom/socket/auth/controller/RefreshController.java
echo -e "\n=== JWTUtil token validation ==="
rg -A 5 'validateToken|verifyToken|checkToken' src/main/java/com/mycom/socket/auth/jwt/JWTUtil.java
Length of output: 4082 Script: #!/bin/bash
# Get complete JWTUtil implementation
echo "=== Complete JWTUtil implementation ==="
cat src/main/java/com/mycom/socket/auth/jwt/JWTUtil.java
Length of output: 4497 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return LoginResponse.of(member.getEmail(), member.getNickname()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -101,5 +112,6 @@ public RegisterResponse register(RegisterRequest request) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public void logout(HttpServletResponse response) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response.addCookie(cookieUtil.createExpiredAuthCookie()); // CookieUtil μ¬μ© | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response.addCookie(cookieUtil.createExpiredRefreshCookie()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -90,15 +90,13 @@ public EmailVerificationResponse verifyCode(String email, String code) { | |||||||||||
| throw new BaseException("μ ν¨νμ§ μμ μΈμ¦ μ½λ νμμ λλ€.", HttpStatus.BAD_REQUEST); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| try { | ||||||||||||
| String saveCode = redisService.getCode(code); // μΈμ¦μ½λ κ²μ¦ | ||||||||||||
| if(!saveCode.equals(code)) { | ||||||||||||
| throw new BaseException("μΈμ¦ μ½λκ° μΌμΉνμ§ μμ΅λλ€.", HttpStatus.BAD_REQUEST); | ||||||||||||
| } | ||||||||||||
| return EmailVerificationResponse.of("μ΄λ©μΌ μΈμ¦μ΄ μλ£λμμ΅λλ€."); | ||||||||||||
| } catch (Exception e) { | ||||||||||||
| String savedCode = redisService.getCode(email); // Redisμμ μ½λλ₯Ό κ°μ Έμ΄ | ||||||||||||
|
|
||||||||||||
|
Comment on lines
+93
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redisμμ κ°μ Έμ¨ μ½λμ null 체ν¬κ° νμν©λλ€.
λ€μκ³Ό κ°μ΄ null 체ν¬λ₯Ό μΆκ°νλ κ²μ κΆμ₯ν©λλ€: String savedCode = redisService.getCode(email); // Redisμμ μ½λλ₯Ό κ°μ Έμ΄
+if (savedCode == null) {
+ throw new BaseException("λ§λ£λμκ±°λ μ‘΄μ¬νμ§ μλ μΈμ¦ μ½λμ
λλ€.", HttpStatus.BAD_REQUEST);
+}π Committable suggestion
Suggested change
|
||||||||||||
| if(!savedCode.equals(code)){ | ||||||||||||
| throw new BaseException("μΈμ¦ μ½λκ° μΌμΉνμ§ μμ΅λλ€.", HttpStatus.BAD_REQUEST); | ||||||||||||
| } | ||||||||||||
| redisService.saveVerifiedEmail(email); | ||||||||||||
| return EmailVerificationResponse.of("μ΄λ©μΌ μΈμ¦μ΄ μλ£λμμ΅λλ€."); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| package com.mycom.socket.member.service; | ||
|
|
||
| import com.mycom.socket.auth.config.JWTProperties; | ||
| import com.mycom.socket.auth.dto.request.LoginRequest; | ||
| import com.mycom.socket.auth.dto.response.LoginResponse; | ||
| import com.mycom.socket.auth.jwt.JWTUtil; | ||
|
|
@@ -13,7 +14,6 @@ | |
| import jakarta.servlet.http.HttpServletResponse; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.junit.jupiter.api.extension.ExtendWith; | ||
| import org.mockito.ArgumentCaptor; | ||
| import org.mockito.InjectMocks; | ||
| import org.mockito.Mock; | ||
| import org.mockito.junit.jupiter.MockitoExtension; | ||
|
|
@@ -36,6 +36,9 @@ class LoginTest { | |
| @Mock | ||
| private PasswordEncoder passwordEncoder; | ||
|
|
||
| @Mock | ||
| private JWTProperties jwtProperties; | ||
|
|
||
|
Comment on lines
+39
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion 리νλ μ ν ν° ν μ€νΈ μΌμ΄μ€ 보μ νμ λ€μ ν μ€νΈ μΌμ΄μ€λ€μ μΆκ°ν΄μΌ ν©λλ€:
@Test
void 리νλ μν ν°_λ§λ£() {
// given
String expiredToken = "expired.refresh.token";
when(jwtUtil.validateToken(expiredToken, "REFRESH_TOKEN")).thenReturn(false);
// when & then
assertThrows(BadRequestException.class,
() -> authService.refreshAccessToken(expiredToken));
}Also applies to: 76-76, 88-89 |
||
| @Mock | ||
| private JWTUtil jwtUtil; | ||
|
|
||
|
|
@@ -70,7 +73,7 @@ class LoginTest { | |
|
|
||
| when(memberRepository.findByEmail(email)).thenReturn(Optional.of(member)); | ||
| when(passwordEncoder.matches(password, encodedPassword)).thenReturn(true); | ||
| when(jwtUtil.createToken(email)).thenReturn(token); | ||
| when(jwtUtil.createToken(email, jwtProperties.getRefreshTokenValidityInSeconds())).thenReturn(token); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion 리νλ μ ν ν° ν μ€νΈ μΌμ΄μ€ 보μμ΄ νμν©λλ€. νμ¬ ν μ€νΈλ 리νλ μ ν ν° μμ±λ§ κ²μ¦νκ³ μμ΅λλ€. λ€μ μλ리μ€μ λν ν μ€νΈλ₯Ό μΆκ°ν΄μ£ΌμΈμ:
ν μ€νΈ μΌμ΄μ€ ꡬνμ λμμ΄ νμνμλ€λ©΄ λ§μν΄ μ£ΌμΈμ. Also applies to: 88-89 |
||
| when(cookieUtil.createAuthCookie(token)).thenReturn(authCookie); // CookieUtil λμ μ μ | ||
|
|
||
| // when | ||
|
|
@@ -82,7 +85,7 @@ class LoginTest { | |
| assertEquals(nickname, response.nickname()); | ||
| verify(memberRepository).findByEmail(email); | ||
| verify(passwordEncoder).matches(password, encodedPassword); | ||
| verify(jwtUtil).createToken(email); | ||
| verify(jwtUtil).createToken(email, jwtProperties.getRefreshTokenValidityInSeconds()); | ||
| verify(cookieUtil).createAuthCookie(token); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π οΈ Refactor suggestion
νμ μμ±μ λν μ ν¨μ± κ²μ¦ μΆκ° νμ
ν ν° μ ν¨ κΈ°κ°κ³Ό μΏ ν€ μ΄λ¦μ νμ κ°μ΄λ―λ‘, μ΄μ λν μ ν¨μ± κ²μ¦μ΄ νμν©λλ€.
λ€μκ³Ό κ°μ΄ μμ νλ κ²μ μ μν©λλ€:
π Committable suggestion