Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion api-test.http
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Content-Type: application/json
"name": "테스터"
}

### 2. DB에 저장된 토큰 조회 (디버깅)
GET http://localhost:8080/debug/tokens

### 2. [Auth] 로그인 및 토큰 발급
# 주의: LoginAuthenticationFilter 구현에 따라 id, password를 헤더로 전송합니다.
POST {{auth_host}}/login
Expand All @@ -24,6 +27,7 @@ password: {{password}}
> {%
// 응답에서 accessToken을 추출하여 전역 변수 'auth_token'에 저장
client.global.set("auth_token", response.body.data.accessToken);
client.global.set("refresh_token", response.body.data.refreshToken);
client.log("Acquired Token: " + response.body.data.accessToken);
%}

Expand All @@ -47,4 +51,15 @@ Authorization: Bearer {{auth_token}}
### 4. [Trip] 생성된 여행 목록 조회 (검증)
GET {{trip_host}}/trips
Content-Type: application/json
Authorization: Bearer {{auth_token}}
Authorization: Bearer {{auth_token}}

### 5. [Auth] 토큰 재발급 (Reissue)
POST {{auth_host}}/auth/reissue
Content-Type: application/json
Cookie: refreshToken={{refresh_token}}

> {%
client.global.set("auth_token", response.body.data.accessToken);
client.global.set("refresh_token", response.body.data.refreshToken);
client.log("Reissued Token: " + response.body.data.accessToken);
%}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.retrip.auth.application.in.CustomOAuth2UserService;
import com.retrip.auth.application.in.MemberQueryService;
import com.retrip.auth.application.out.repository.RefreshTokenRepository;
import com.retrip.auth.infra.adapter.in.rest.filter.JwtAuthenticationFilter;
import com.retrip.auth.infra.adapter.in.rest.filter.LoginAuthenticationFilter;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -32,7 +33,7 @@ public class SecurityConfig {

private final CustomOAuth2UserService customOAuth2UserService;
private final OAuth2LoginSuccessHandler oAuth2LoginSuccessHandler;

private final RefreshTokenRepository refreshTokenRepository;
private final JwtAuthenticationFilter jwtAuthenticationFilter;

@Bean
Expand Down Expand Up @@ -63,7 +64,7 @@ public LoginAuthenticationFilter loginAuthenticationFilter(
JwtConfig jwtConfig,
AuthenticationManager authenticationManager,
JwtProvider jwtProvider) {
LoginAuthenticationFilter filter = new LoginAuthenticationFilter(jwtConfig, authenticationManager,jwtProvider);
LoginAuthenticationFilter filter = new LoginAuthenticationFilter(jwtConfig, authenticationManager,jwtProvider,refreshTokenRepository);
return filter;
}

Expand Down Expand Up @@ -104,6 +105,7 @@ public SecurityFilterChain securityFilterChain(
"/swagger-resources/**",
"/webjars/**"
).permitAll()
.requestMatchers("/debug/**").permitAll()

.anyRequest().authenticated()
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.retrip.auth.domain.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
Expand All @@ -16,11 +17,12 @@
public class RefreshToken {

@Id
@Column(length = 1024)
private String tokenValue;

private String memberId;

@Column(length = 1024)
private String authorities;


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.retrip.auth.application.config.JwtConfig;
import com.retrip.auth.application.config.JwtProvider; // [추가]
import com.retrip.auth.application.config.JwtProvider;
import com.retrip.auth.application.config.UsernamePasswordAuthentication;
import com.retrip.auth.application.in.response.LoginResponse;
import com.retrip.auth.application.out.repository.RefreshTokenRepository;
import com.retrip.auth.domain.entity.RefreshToken;
import com.retrip.auth.infra.adapter.in.rest.common.ApiResponse;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
Expand All @@ -15,18 +17,21 @@
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
public class LoginAuthenticationFilter extends OncePerRequestFilter {

private final JwtConfig jwtConfig;
private final AuthenticationManager manager;
private final JwtProvider jwtProvider; // [추가] 토큰 생성기 주입
private final JwtProvider jwtProvider;
private final RefreshTokenRepository refreshTokenRepository;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
Expand All @@ -37,7 +42,6 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
String password = request.getHeader("password");

if (!StringUtils.hasText(id) || !StringUtils.hasText(password)) {
// 값이 없으면 400 Bad Request가 더 적절하지만, 기존 로직 유지
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
Expand All @@ -47,10 +51,21 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
Authentication authentication = new UsernamePasswordAuthentication(id, password);
Authentication auth = manager.authenticate(authentication);

// 3. [핵심 변경] JwtProvider를 통해 RSA 서명된 토큰 생성
// 기존의 복잡한 generateToken 메서드 삭제 -> 위임
// 3. 토큰 생성
LoginResponse.TokenResponse tokenResponse = jwtProvider.generateTokens(auth);

// 3-1. Refresh Token DB에 저장
String authorities = auth.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(","));

RefreshToken refreshToken = new RefreshToken(
tokenResponse.refreshToken(),
auth.getName(), // memberId
authorities
);
refreshTokenRepository.save(refreshToken);

// 4. 응답 작성
ApiResponse<LoginResponse.TokenResponse> result = ApiResponse.ok(tokenResponse);

Expand All @@ -63,15 +78,13 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
response.getWriter().flush();

} catch (AuthenticationException e) {
// 인증 실패 시 처리
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}


@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
// /login 경로만 필터 적용 (나머지는 통과 -> true 반환)
return !request.getRequestURI().equals("/login");
}
}