diff --git a/.github/workflows/dev-CI.yml b/.github/workflows/dev-CI.yml index 12f8ead8..457af248 100644 --- a/.github/workflows/dev-CI.yml +++ b/.github/workflows/dev-CI.yml @@ -84,11 +84,11 @@ jobs: docker build -f Dockerfile-dev --platform linux/amd64 -t hoonyworld/beat-dev . docker push hoonyworld/beat-dev - # Trigger Jenkins job - Jenkins 작업 트리거 - - name: Trigger Jenkins job - uses: appleboy/jenkins-action@master - with: - url: ${{ secrets.DEV_WEBHOOK_URL }} - user: "beat" - token: ${{ secrets.DEV_JENKINS_API_TOKEN }} - job: "beat-project" \ No newline at end of file +# # Trigger Jenkins job - Jenkins 작업 트리거 +# - name: Trigger Jenkins job +# uses: appleboy/jenkins-action@master +# with: +# url: ${{ secrets.DEV_WEBHOOK_URL }} +# user: "beat" +# token: ${{ secrets.DEV_JENKINS_API_TOKEN }} +# job: "beat-project" \ No newline at end of file diff --git a/src/main/java/com/beat/domain/member/application/MemberRegistrationService.java b/src/main/java/com/beat/domain/member/application/MemberRegistrationService.java index 6c3ae043..1f3b895c 100644 --- a/src/main/java/com/beat/domain/member/application/MemberRegistrationService.java +++ b/src/main/java/com/beat/domain/member/application/MemberRegistrationService.java @@ -6,31 +6,43 @@ import com.beat.domain.user.domain.Role; import com.beat.domain.user.domain.Users; import com.beat.global.auth.client.dto.MemberInfoResponse; + import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +@Slf4j @Service @RequiredArgsConstructor public class MemberRegistrationService { - private final UserRepository userRepository; - private final MemberRepository memberRepository; - - @Transactional - public Long registerMemberWithUserInfo(final MemberInfoResponse memberInfoResponse) { - Users users = Users.createWithRole(Role.MEMBER); - users = userRepository.save(users); - - Member member = Member.create( - memberInfoResponse.nickname(), - memberInfoResponse.email(), - users, - memberInfoResponse.socialId(), - memberInfoResponse.socialType() - ); - - memberRepository.save(member); - return member.getId(); - } + private final UserRepository userRepository; + private final MemberRepository memberRepository; + + @Transactional + public Long registerMemberWithUserInfo(final MemberInfoResponse memberInfoResponse) { + Users users = Users.createWithRole(Role.MEMBER); + + log.info("Granting MEMBER role to new user with role: {}", users.getRole()); + + users = userRepository.save(users); + + log.info("Registering new user with role: {}", users.getRole()); + + Member member = Member.create( + memberInfoResponse.nickname(), + memberInfoResponse.email(), + users, + memberInfoResponse.socialId(), + memberInfoResponse.socialType() + ); + + memberRepository.save(member); + + log.info("Member registered with memberId: {}, role: {}", member.getId(), users.getRole()); + + return member.getId(); + } } \ No newline at end of file diff --git a/src/main/java/com/beat/global/auth/jwt/filter/JwtAuthenticationFilter.java b/src/main/java/com/beat/global/auth/jwt/filter/JwtAuthenticationFilter.java index 61b220ee..9177cca6 100644 --- a/src/main/java/com/beat/global/auth/jwt/filter/JwtAuthenticationFilter.java +++ b/src/main/java/com/beat/global/auth/jwt/filter/JwtAuthenticationFilter.java @@ -5,10 +5,12 @@ import com.beat.global.auth.jwt.provider.JwtValidationType; import com.beat.global.auth.security.AdminAuthentication; import com.beat.global.auth.security.MemberAuthentication; + import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + import java.io.IOException; import java.util.Collection; import java.util.List; @@ -16,6 +18,7 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -29,77 +32,81 @@ @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { - private final JwtTokenProvider jwtTokenProvider; - - @Override - protected void doFilterInternal(@NonNull HttpServletRequest request, - @NonNull HttpServletResponse response, - @NonNull FilterChain filterChain) throws ServletException, IOException { - - final String token = getJwtFromRequest(request); - - if (!StringUtils.hasText(token)) { - log.info("JWT Token not found in request header. Assuming guest access or public API request."); - filterChain.doFilter(request, response); - return; - } - - try { - JwtValidationType validationType = jwtTokenProvider.validateToken(token); - - if (validationType == JwtValidationType.VALID_JWT) { - setAuthentication(token, request); - filterChain.doFilter(request, response); - } else { - handleInvalidToken(validationType, response); - } - } catch (Exception e) { - log.error("JWT Authentication Exception: ", e); - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 응답 - } - } - - private void setAuthentication(String token, HttpServletRequest request) { - Long memberId = jwtTokenProvider.getMemberIdFromJwt(token); - Role role = jwtTokenProvider.getRoleFromJwt(token); - - Collection authorities = List.of(role.toGrantedAuthority()); - UsernamePasswordAuthenticationToken authentication = createAuthentication(memberId, authorities, role); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - - SecurityContextHolder.getContext().setAuthentication(authentication); - log.info("Authentication set for memberId: {}, role: {}", memberId, role); - } - - private void handleInvalidToken(JwtValidationType validationType, HttpServletResponse response) { - if (validationType == JwtValidationType.EXPIRED_JWT_TOKEN) { - log.warn("JWT Token is expired"); - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 응답 - } else { - log.warn("JWT Token is invalid"); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400 응답 - } - } - - private UsernamePasswordAuthenticationToken createAuthentication(Long memberId, Collection authorities, Role role) { - log.info("Creating authentication for memberId: {} with role: {}", memberId, role); - - if (role == Role.ADMIN) { - log.info("Creating AdminAuthentication for memberId: {}", memberId); - return new AdminAuthentication(memberId.toString(), null, authorities); - } else if (role == Role.MEMBER) { - log.info("Creating MemberAuthentication for memberId: {}", memberId); - return new MemberAuthentication(memberId.toString(), null, authorities); - } - log.error("Unknown role: {}", role); - throw new IllegalArgumentException("Unknown role: " + role); - } - - private String getJwtFromRequest(HttpServletRequest request) { - String bearerToken = request.getHeader("Authorization"); - if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { - return bearerToken.substring("Bearer ".length()); - } - return null; - } + private final JwtTokenProvider jwtTokenProvider; + + @Override + protected void doFilterInternal(@NonNull HttpServletRequest request, + @NonNull HttpServletResponse response, + @NonNull FilterChain filterChain) throws ServletException, IOException { + + final String token = getJwtFromRequest(request); + + if (!StringUtils.hasText(token)) { + log.info("JWT Token not found in request header. Assuming guest access or public API request."); + filterChain.doFilter(request, response); + return; + } + + try { + JwtValidationType validationType = jwtTokenProvider.validateToken(token); + + if (validationType == JwtValidationType.VALID_JWT) { + setAuthentication(token, request); + filterChain.doFilter(request, response); + } else { + handleInvalidToken(validationType, response); + } + } catch (Exception e) { + log.error("JWT Authentication Exception: ", e); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 응답 + } + } + + private void setAuthentication(String token, HttpServletRequest request) { + Long memberId = jwtTokenProvider.getMemberIdFromJwt(token); + Role role = jwtTokenProvider.getRoleFromJwt(token); + + log.info("Setting authentication for memberId: {} with role: {}", memberId, role); + + Collection authorities = List.of(role.toGrantedAuthority()); + UsernamePasswordAuthenticationToken authentication = createAuthentication(memberId, authorities, role); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + + log.info("Authentication set: memberId: {}, role: {}", memberId, role); + + SecurityContextHolder.getContext().setAuthentication(authentication); + } + + private void handleInvalidToken(JwtValidationType validationType, HttpServletResponse response) { + if (validationType == JwtValidationType.EXPIRED_JWT_TOKEN) { + log.warn("JWT Token is expired"); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 응답 + } else { + log.warn("JWT Token is invalid"); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400 응답 + } + } + + private UsernamePasswordAuthenticationToken createAuthentication(Long memberId, + Collection authorities, Role role) { + log.info("Creating authentication for memberId: {} with role: {}", memberId, role); + + if (role == Role.ADMIN) { + log.info("Creating AdminAuthentication for memberId: {}", memberId); + return new AdminAuthentication(memberId.toString(), null, authorities); + } else if (role == Role.MEMBER) { + log.info("Creating MemberAuthentication for memberId: {}", memberId); + return new MemberAuthentication(memberId.toString(), null, authorities); + } + log.error("Unknown role: {}", role); + throw new IllegalArgumentException("Unknown role: " + role); + } + + private String getJwtFromRequest(HttpServletRequest request) { + String bearerToken = request.getHeader("Authorization"); + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { + return bearerToken.substring("Bearer ".length()); + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/beat/global/auth/jwt/provider/JwtTokenProvider.java b/src/main/java/com/beat/global/auth/jwt/provider/JwtTokenProvider.java index 1ac3f191..b7e581ed 100644 --- a/src/main/java/com/beat/global/auth/jwt/provider/JwtTokenProvider.java +++ b/src/main/java/com/beat/global/auth/jwt/provider/JwtTokenProvider.java @@ -57,15 +57,21 @@ public String issueRefreshToken(final Authentication authentication) { private String issueToken(final Authentication authentication, final long expiredTime) { final Date now = new Date(); - final Claims claims = Jwts.claims() - .setIssuedAt(now) - .setExpiration(new Date(now.getTime() + expiredTime)); + final Claims claims = Jwts.claims().setIssuedAt(now).setExpiration(new Date(now.getTime() + expiredTime)); claims.put(MEMBER_ID, authentication.getPrincipal()); - claims.put(ROLE_KEY, authentication.getAuthorities().stream() + + log.info("Authorities before token generation: {}", authentication.getAuthorities()); + + String role = authentication.getAuthorities() + .stream() .map(GrantedAuthority::getAuthority) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("No authorities found for user"))); + .orElseThrow(() -> new IllegalArgumentException("No authorities found for user")); + + log.info("Selected role for token: {}", role); + + claims.put(ROLE_KEY, role); return Jwts.builder() .setHeaderParam(Header.TYPE, Header.JWT_TYPE) @@ -102,11 +108,7 @@ public JwtValidationType validateToken(String token) { } private Claims getBody(final String token) { - return Jwts.parserBuilder() - .setSigningKey(getSigningKey()) - .build() - .parseClaimsJws(token) - .getBody(); + return Jwts.parserBuilder().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody(); } public Long getMemberIdFromJwt(String token) { @@ -123,9 +125,11 @@ public Role getRoleFromJwt(String token) { Claims claims = getBody(token); String roleName = claims.get(ROLE_KEY, String.class); + log.info("Extracted role from JWT: {}", roleName); + // "ROLE_" 접두사 제거 String enumValue = roleName.replace("ROLE_", ""); - log.info("Extracted role from JWT: {}", enumValue); + log.info("Final role after processing: {}", enumValue); return Role.valueOf(enumValue.toUpperCase()); }