
1. 리프레시 토큰(Refresh Token) 개요
리프레시 토큰(Refresh Token)은 JWT 기반 인증 시스템에서 액세스 토큰(Access Token)의 만료 후에도 재인증 없이 새로운 액세스 토큰을 발급할 수 있도록 도와주는 토큰이다. 일반적으로 액세스 토큰은 보안 강화를 위해 짧은 만료 시간을 가지며, 이를 보완하기 위해 리프레시 토큰이 사용된다.
✅ 리프레시 토큰의 필요성
- 액세스 토큰이 짧은 만료 시간을 가져 보안성이 강화됨
- 사용자가 다시 로그인할 필요 없이 자동으로 새로운 액세스 토큰 발급 가능
- 서버에서 세션을 관리하지 않고도 인증을 유지할 수 있음
1.1. 리프레시 토큰의 동작 방식
- 사용자가 로그인하면 액세스 토큰과 리프레시 토큰을 함께 발급한다.
- 클라이언트는 액세스 토큰을 사용하여 API 요청을 수행한다.
- 액세스 토큰이 만료되면 리프레시 토큰을 사용하여 새로운 액세스 토큰을 요청한다.
- 서버는 리프레시 토큰을 검증한 후 새로운 액세스 토큰을 발급한다.
1.2. 리프레시 토큰 발급 및 사용
✅ 리프레시 토큰을 포함한 JWT 생성
String refreshToken = Jwts.builder()
.subject(userEntity.getUsername())
.expiration(new Date(System.currentTimeMillis() + 604800000)) // 7일
.signWith(secretKey, Jwts.SIG.HS256)
.compact();
✅ 리프레시 토큰을 이용한 액세스 토큰 재발급 API
@PostMapping("/auth/refresh")
public ResponseEntity<?> refreshAccessToken(@RequestBody TokenRequest request) {
String refreshToken = request.getRefreshToken();
if (jwtUtils.validateToken(refreshToken)) {
String newAccessToken = jwtUtils.generateAccessToken(jwtUtils.getSubjectFromToken(refreshToken));
return ResponseEntity.ok(new TokenResponse(newAccessToken));
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid refresh token");
}
✅ 리프레시 토큰을 안전하게 관리하는 방법
- 데이터베이스에 저장하여 유효성을 검사할 수 있도록 함
- 쿠키에 저장 시 HttpOnly, Secure 속성 적용하여 보안 강화
- 유출될 경우 즉시 무효화할 수 있는 방법 제공 (로그아웃 시 삭제)
2. OAuth2 인증 방식
OAuth2는 서드파티 애플리케이션이 사용자 인증 및 권한 부여를 안전하게 수행할 수 있도록 지원하는 인증 프로토콜이다. Google, Facebook, GitHub 등의 서비스에서 제공하는 인증 방식을 지원한다.
✅ OAuth2의 주요 개념
개념설명
| Resource Owner | 사용자 (OAuth2 인증을 받는 주체) |
| Client | 인증을 요청하는 서드파티 애플리케이션 |
| Authorization Server | 인증을 수행하고 토큰을 발급하는 서버 |
| Resource Server | 보호된 자원(API)을 제공하는 서버 |
| Access Token | 보호된 자원 접근을 위한 인증 토큰 |
2.1. OAuth2 인증 흐름
- 클라이언트(서드파티 애플리케이션)가 인증 서버에 인증 요청을 보냄
- 사용자가 로그인 및 권한 부여를 수행함
- 인증 서버가 인가 코드(Authorization Code)를 반환
- 클라이언트가 인가 코드를 이용해 액세스 토큰을 요청
- 인증 서버가 액세스 토큰을 발급하고 클라이언트가 이를 사용하여 API 요청 수행
✅ OAuth2를 활용한 인증 예제 (Spring Security 적용)
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.oauth2Login(oauth2 -> oauth2
.loginPage("/oauth2/authorization/google")
.defaultSuccessUrl("/home", true)
);
return http.build();
}
}
위 설정을 통해 Google OAuth2 로그인을 지원하는 Spring Security 설정을 적용할 수 있다.
2.2. OAuth2 로그인 후 사용자 정보 가져오기
OAuth2 인증 후 사용자의 정보를 가져오려면 OAuth2UserService를 활용할 수 있다.
@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = new DefaultOAuth2UserService().loadUser(userRequest);
return new DefaultOAuth2User(oAuth2User.getAuthorities(), oAuth2User.getAttributes(), "email");
}
}
2.3. OAuth2 리프레시 토큰 활용
OAuth2를 사용할 때도 리프레시 토큰을 활용하여 자동 로그인 및 세션 유지가 가능하다.
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;
@GetMapping("/refresh-token")
public ResponseEntity<String> refreshToken(@AuthenticationPrincipal OAuth2User user) {
OAuth2AuthorizedClient client = authorizedClientService.loadAuthorizedClient("google", user.getName());
String refreshToken = client.getRefreshToken().getTokenValue();
return ResponseEntity.ok(refreshToken);
}
}
3. 마무리
이번 강의를 통해 리프레시 토큰과 OAuth2 인증 방식에 대해 학습했다.
✅ 리프레시 토큰을 활용하면
- 액세스 토큰 만료 시에도 로그인을 다시 수행할 필요가 없음
- 보안성을 유지하면서 사용자 경험을 개선할 수 있음
✅ OAuth2 인증 방식을 활용하면
- Google, Facebook, GitHub 등의 소셜 로그인 기능을 쉽게 구현 가능
- 사용자 정보를 인증 서버에서 제공하여 별도의 로그인 시스템 구축이 불필요함
이 글은 LG CNS AM Inspire Camp 1기 진행 중 Obsidian에 정리해뒀던 글을 블로그에 옮긴 글입니다.
'Experience > LG CNS AM Inspire Camp 1기' 카테고리의 다른 글
| [LG CNS AM Inspire Camp] 19. Jenkins 기반 CI/CD 파이프라인 구축 (0) | 2025.05.14 |
|---|---|
| [LG CNS AM Inspire Camp] 18. 클라우드 네이티브와 Docker (0) | 2025.03.05 |
| [LG CNS AM Inspire Camp] 16. Spring Security (with Session, Cookie, JWT) (0) | 2025.02.10 |
| [LG CNS AM Inspire Camp] 15. 스프링 부트와 MyBatis를 활용한 데이터베이스 연동 (0) | 2025.02.10 |
| [LG CNS AM Inspire Camp] 14. 스프링 프레임워크와 스프링빈, AOP (0) | 2025.02.10 |