Skip to content

Commit 19abafc

Browse files
authored
Merge pull request #18 from AI-Tutor-2024/auth
[FIX] sign-in api 작동 오류에 따른 변경사항
2 parents 736cfe0 + 115a385 commit 19abafc

File tree

8 files changed

+84
-83
lines changed

8 files changed

+84
-83
lines changed

src/main/java/com/example/ai_tutor/domain/auth/application/AuthService.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
@Transactional(readOnly = true)
3333
public class AuthService {
3434

35-
private final JwtUtil jwtUtil;
35+
private final CustomTokenProviderService customTokenProviderService;
3636
private final AuthenticationManager authenticationManager;
3737

3838
private final TokenRepository tokenRepository;
@@ -47,17 +47,17 @@ public ResponseEntity<?> refresh(RefreshTokenReq tokenRefreshRequest){
4747

4848
Token token = tokenRepository.findByRefreshToken(tokenRefreshRequest.getRefreshToken())
4949
.orElseThrow(InvalidTokenException::new);
50-
Authentication authentication = jwtUtil.getAuthenticationByEmail(token.getUserEmail());
50+
Authentication authentication = customTokenProviderService.getAuthenticationByEmail(token.getUserEmail());
5151

5252
//refresh token 정보 값을 업데이트 한다.
5353
//시간 유효성 확인
5454
TokenMapping tokenMapping;
5555

56-
Long expirationTime = jwtUtil.getExpiration(tokenRefreshRequest.getRefreshToken());
56+
Long expirationTime = customTokenProviderService.getExpiration(tokenRefreshRequest.getRefreshToken());
5757
if(expirationTime > 0){
58-
tokenMapping = jwtUtil.refreshToken(authentication, token.getRefreshToken());
58+
tokenMapping = customTokenProviderService.refreshToken(authentication, token.getRefreshToken());
5959
}else{
60-
tokenMapping = jwtUtil.createToken(authentication);
60+
tokenMapping = customTokenProviderService.createToken(authentication);
6161
}
6262

6363
Token updateToken = token.updateRefreshToken(tokenMapping.getRefreshToken());
@@ -93,15 +93,15 @@ public ResponseEntity<?> signOut(UserPrincipal userPrincipal){
9393
private boolean valid(String refreshToken){
9494

9595
//1. 토큰 형식 물리적 검증
96-
boolean validateCheck = jwtUtil.validateToken(refreshToken);
96+
boolean validateCheck = customTokenProviderService.validateToken(refreshToken);
9797
DefaultAssert.isTrue(validateCheck, "Token 검증에 실패하였습니다.");
9898

9999
//2. refresh token 값을 불러온다.
100100
Optional<Token> token = tokenRepository.findByRefreshToken(refreshToken);
101101
DefaultAssert.isTrue(token.isPresent(), "탈퇴 처리된 회원입니다.");
102102

103103
//3. email 값을 통해 인증값을 불러온다
104-
Authentication authentication = jwtUtil.getAuthenticationByEmail(token.get().getUserEmail());
104+
Authentication authentication = customTokenProviderService.getAuthenticationByEmail(token.get().getUserEmail());
105105
DefaultAssert.isTrue(token.get().getUserEmail().equals(authentication.getName()), "사용자 인증에 실패하였습니다.");
106106

107107
return true;
@@ -120,10 +120,10 @@ public ResponseEntity<?> signIn(SignInReq signInReq) {
120120
);
121121
SecurityContextHolder.getContext().setAuthentication(authentication);
122122

123-
TokenMapping tokenMapping = jwtUtil.createToken(authentication);
123+
TokenMapping tokenMapping = customTokenProviderService.createToken(authentication);
124124
Token token = Token.builder()
125125
.refreshToken(tokenMapping.getRefreshToken())
126-
.userEmail(tokenMapping.getUserEmail())
126+
.userEmail(tokenMapping.getEmail())
127127
.build();
128128
tokenRepository.save(token);
129129

src/main/java/com/example/ai_tutor/domain/auth/application/JwtUtil.java renamed to src/main/java/com/example/ai_tutor/domain/auth/application/CustomTokenProviderService.java

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,25 @@
66
import io.jsonwebtoken.*;
77
import io.jsonwebtoken.io.Decoders;
88
import io.jsonwebtoken.security.Keys;
9+
import lombok.RequiredArgsConstructor;
910
import lombok.extern.slf4j.Slf4j;
1011
import org.springframework.beans.factory.annotation.Autowired;
1112
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
1213
import org.springframework.security.core.userdetails.UserDetails;
1314
import org.springframework.security.core.Authentication;
1415
import org.springframework.stereotype.Service;
1516

17+
import java.nio.charset.StandardCharsets;
1618
import java.security.Key;
1719
import java.util.Date;
1820

1921
@Slf4j
2022
@Service
21-
public class JwtUtil {
22-
23-
@Autowired
24-
private OAuth2Config oAuth2Config;
25-
26-
@Autowired
27-
private CustomUserDetailsService customUserDetailsService;
28-
23+
@RequiredArgsConstructor
24+
public class CustomTokenProviderService {
2925

26+
private final OAuth2Config oAuth2Config;
27+
private final CustomUserDetailsService customUserDetailsService;
3028

3129
public TokenMapping createToken(Authentication authentication) {
3230
UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
@@ -36,9 +34,8 @@ public TokenMapping createToken(Authentication authentication) {
3634
Date accessTokenExpiresIn = new Date(now.getTime() + oAuth2Config.getAuth().getAccessTokenExpirationMsec());
3735
Date refreshTokenExpiresIn = new Date(now.getTime() + oAuth2Config.getAuth().getRefreshTokenExpirationMsec());
3836

39-
String secretKey = oAuth2Config.getAuth().getTokenSecret();
40-
41-
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
37+
String base64SecretKey = oAuth2Config.getAuth().getTokenSecret();
38+
byte[] keyBytes = Decoders.BASE64.decode(base64SecretKey);
4239
Key key = Keys.hmacShaKeyFor(keyBytes);
4340

4441
String accessToken = Jwts.builder()
@@ -54,7 +51,7 @@ public TokenMapping createToken(Authentication authentication) {
5451
.compact();
5552

5653
return TokenMapping.builder()
57-
.userEmail(userPrincipal.getEmail())
54+
.email(userPrincipal.getEmail())
5855
.accessToken(accessToken)
5956
.refreshToken(refreshToken)
6057
.build();
@@ -71,14 +68,14 @@ public TokenMapping refreshToken(Authentication authentication, String refreshTo
7168
Key key = Keys.hmacShaKeyFor(keyBytes);
7269

7370
String accessToken = Jwts.builder()
74-
.setSubject(Long.toString(userPrincipal.getId()))
71+
.setSubject(userPrincipal.getEmail())
7572
.setIssuedAt(new Date())
7673
.setExpiration(accessTokenExpiresIn)
7774
.signWith(key, SignatureAlgorithm.HS512)
7875
.compact();
7976

8077
return TokenMapping.builder()
81-
.userEmail(userPrincipal.getEmail())
78+
.email(userPrincipal.getEmail())
8279
.accessToken(accessToken)
8380
.refreshToken(refreshToken)
8481
.build();
@@ -101,33 +98,52 @@ public UsernamePasswordAuthenticationToken getAuthenticationById(String token){
10198
return authentication;
10299
}
103100

104-
public UsernamePasswordAuthenticationToken getAuthenticationByEmail(String email){
101+
102+
103+
public String getEmailFromToken(String token) {
104+
log.debug("Extracting email from token: {}", token); // 추가된 로깅
105+
Claims claims = Jwts.parserBuilder()
106+
.setSigningKey(oAuth2Config.getAuth().getTokenSecret())
107+
.build()
108+
.parseClaimsJws(token)
109+
.getBody();
110+
111+
String email = claims.getSubject();
112+
log.debug("Email extracted: {}", email); // 추가된 로깅
113+
return email;
114+
}
115+
116+
public UsernamePasswordAuthenticationToken getAuthenticationByEmail(String token) {
117+
String email = getEmailFromToken(token);
105118
UserDetails userDetails = customUserDetailsService.loadUserByUsername(email);
106-
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
107-
return authentication;
119+
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
108120
}
109121

110122
public Long getExpiration(String token) {
111123
// accessToken 남은 유효시간
112-
Date expiration = Jwts.parserBuilder().setSigningKey(oAuth2Config.getAuth().getTokenSecret()).build().parseClaimsJws(token).getBody().getExpiration();
124+
Date expiration = Jwts.parserBuilder()
125+
.setSigningKey(oAuth2Config.getAuth().getTokenSecret())
126+
.build()
127+
.parseClaimsJws(token)
128+
.getBody()
129+
.getExpiration();
113130
// 현재 시간
114131
Long now = new Date().getTime();
115-
//시간 계산
132+
// 시간 계산
116133
return (expiration.getTime() - now);
117134
}
118135

119136
public boolean validateToken(String token) {
120137
try {
121-
log.info("JWT 검증 시작 - 토큰: {}", token);
138+
log.info("Validating token: {}", token);
139+
140+
String base64SecretKey = oAuth2Config.getAuth().getTokenSecret();
141+
byte[] keyBytes = Decoders.BASE64.decode(base64SecretKey);
142+
Key key = Keys.hmacShaKeyFor(keyBytes);
122143

123-
String secretKey = oAuth2Config.getAuth().getTokenSecret();
124-
if (secretKey == null || secretKey.isEmpty()) {
125-
log.error("JWT 서명 검증 실패 - Secret Key가 설정되지 않았음");
126-
return false;
127-
}
128144

129145
Jwts.parserBuilder()
130-
.setSigningKey(secretKey)
146+
.setSigningKey(key)
131147
.build()
132148
.parseClaimsJws(token);
133149

@@ -150,7 +166,6 @@ public boolean validateToken(String token) {
150166
} catch (Exception ex) {
151167
log.error("예기치 않은 JWT 검증 오류 발생: {}", ex.getMessage(), ex);
152168
}
153-
154169
return false;
155170
}
156171

src/main/java/com/example/ai_tutor/domain/auth/application/CustomUserDetailsService.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
import com.example.ai_tutor.global.config.security.token.UserPrincipal;
77
import jakarta.transaction.Transactional;
88
import lombok.RequiredArgsConstructor;
9+
import lombok.extern.slf4j.Slf4j;
910
import org.springframework.security.core.userdetails.UserDetails;
1011
import org.springframework.security.core.userdetails.UserDetailsService;
1112
import org.springframework.security.core.userdetails.UsernameNotFoundException;
1213
import org.springframework.stereotype.Service;
1314

1415
import java.util.Optional;
1516

17+
@Slf4j
1618
@RequiredArgsConstructor
1719
@Service
1820
public class CustomUserDetailsService implements UserDetailsService {
@@ -21,21 +23,21 @@ public class CustomUserDetailsService implements UserDetailsService {
2123

2224
@Override
2325
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
24-
26+
log.debug("Trying to load user by email: {}", email);
2527
User user = userRepository.findByEmail(email)
26-
.orElseThrow(() ->
27-
new UsernameNotFoundException("유저 정보를 찾을 수 없습니다.")
28-
);
28+
.orElseThrow(() -> new UsernameNotFoundException("유저 정보를 찾을 수 없습니다."));
2929

30+
log.debug("User found: {}", user);
3031
return UserPrincipal.create(user);
3132
}
3233

3334
@Transactional
3435
public UserDetails loadUserById(Long id) {
36+
log.debug("Trying to load user by ID: {}", id);
3537
Optional<User> user = userRepository.findById(id);
3638
DefaultAssert.isOptionalPresent(user);
3739

40+
log.debug("User found by ID: {}", user);
3841
return UserPrincipal.create(user.get());
3942
}
40-
41-
}
43+
}
Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
package com.example.ai_tutor.domain.auth.dto;
22

3+
import lombok.AllArgsConstructor;
34
import lombok.Builder;
45
import lombok.Getter;
56
import lombok.NoArgsConstructor;
67

8+
@Builder
9+
@AllArgsConstructor
10+
@NoArgsConstructor
711
@Getter
812
public class TokenMapping {
9-
private String userEmail;
13+
private String email;
1014
private String accessToken;
1115
private String refreshToken;
12-
13-
public TokenMapping(){}
14-
15-
@Builder
16-
public TokenMapping(String userEmail, String accessToken, String refreshToken){
17-
this.userEmail = userEmail;
18-
this.accessToken = accessToken;
19-
this.refreshToken = refreshToken;
20-
}
21-
2216
}

src/main/java/com/example/ai_tutor/global/config/security/handler/CustomSimpleUrlAuthenticationSuccessHandler.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,27 @@
11
package com.example.ai_tutor.global.config.security.handler;
22

3-
import com.example.ai_tutor.domain.auth.application.JwtUtil;
3+
import com.example.ai_tutor.domain.auth.application.CustomTokenProviderService;
44
import com.example.ai_tutor.domain.auth.domain.Token;
55
import com.example.ai_tutor.domain.auth.domain.repository.CustomAuthorizationRequestRepository;
66
import com.example.ai_tutor.domain.auth.domain.repository.TokenRepository;
77
import com.example.ai_tutor.domain.auth.dto.TokenMapping;
8-
import com.example.ai_tutor.global.DefaultAssert;
9-
import com.example.ai_tutor.global.config.security.OAuth2Config;
10-
import com.example.ai_tutor.global.config.security.util.CustomCookie;
118
import jakarta.servlet.ServletException;
12-
import jakarta.servlet.http.Cookie;
139
import jakarta.servlet.http.HttpServletRequest;
1410
import jakarta.servlet.http.HttpServletResponse;
1511
import lombok.RequiredArgsConstructor;
1612
import lombok.extern.slf4j.Slf4j;
1713
import org.springframework.security.core.Authentication;
1814
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
1915
import org.springframework.stereotype.Component;
20-
import org.springframework.web.util.UriComponentsBuilder;
2116

2217
import java.io.IOException;
23-
import java.net.URI;
24-
import java.util.Optional;
25-
26-
import static com.example.ai_tutor.domain.auth.domain.repository.CustomAuthorizationRequestRepository.REDIRECT_URI_PARAM_COOKIE_NAME;
2718

2819
@Slf4j
2920
@RequiredArgsConstructor
3021
@Component
3122
public class CustomSimpleUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
3223

33-
private final JwtUtil jwtUtil; // JWT 생성 유틸
24+
private final CustomTokenProviderService customTokenProviderService; // JWT 생성 유틸
3425
private final TokenRepository tokenRepository;
3526
private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository;
3627

@@ -46,11 +37,11 @@ public void onAuthenticationSuccess(HttpServletRequest request,
4637
}
4738

4839
// 1) JWT 토큰 생성
49-
TokenMapping tokenMapping = jwtUtil.createToken(authentication);
40+
TokenMapping tokenMapping = customTokenProviderService.createToken(authentication);
5041

51-
// 2) RefreshToken 저장 (DB or Redis etc.)
42+
// 2) RefreshToken 저장
5243
Token token = Token.builder()
53-
.userEmail(tokenMapping.getUserEmail())
44+
.userEmail(tokenMapping.getEmail())
5445
.refreshToken(tokenMapping.getRefreshToken())
5546
.build();
5647
tokenRepository.save(token);

src/main/java/com/example/ai_tutor/global/config/security/token/JwtAuthenticationFilter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.example.ai_tutor.global.config.security.token;
22

3-
import com.example.ai_tutor.domain.auth.application.JwtUtil;
3+
import com.example.ai_tutor.domain.auth.application.CustomTokenProviderService;
44
import jakarta.servlet.FilterChain;
55
import jakarta.servlet.ServletException;
66
import jakarta.servlet.http.HttpServletRequest;
@@ -19,7 +19,7 @@
1919
public class JwtAuthenticationFilter extends OncePerRequestFilter {
2020

2121
@Autowired
22-
private JwtUtil jwtUtil;
22+
private CustomTokenProviderService customTokenProviderService;
2323

2424
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
2525
public static final String BEARER_TOKEN_PREFIX = "Bearer ";
@@ -29,8 +29,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
2929
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
3030
String jwt = getJwtFromRequest(request);
3131

32-
if (StringUtils.hasText(jwt) && jwtUtil.validateToken(jwt)) {
33-
UsernamePasswordAuthenticationToken authentication = jwtUtil.getAuthenticationById(jwt);
32+
if (StringUtils.hasText(jwt) && customTokenProviderService.validateToken(jwt)) {
33+
UsernamePasswordAuthenticationToken authentication = customTokenProviderService.getAuthenticationByEmail(jwt);
3434
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
3535
SecurityContextHolder.getContext().setAuthentication(authentication);
3636
}

0 commit comments

Comments
 (0)