Experience/LG CNS AM Inspire Camp 1기

[LG CNS AM Inspire Camp] 17. 리프레시 토큰과 OAuth2 인증 방식

chillmyh 2025. 2. 10. 19:40

1. 리프레시 토큰(Refresh Token) 개요

리프레시 토큰(Refresh Token)은 JWT 기반 인증 시스템에서 액세스 토큰(Access Token)의 만료 후에도 재인증 없이 새로운 액세스 토큰을 발급할 수 있도록 도와주는 토큰이다. 일반적으로 액세스 토큰은 보안 강화를 위해 짧은 만료 시간을 가지며, 이를 보완하기 위해 리프레시 토큰이 사용된다.

 

리프레시 토큰의 필요성

  • 액세스 토큰이 짧은 만료 시간을 가져 보안성이 강화됨
  • 사용자가 다시 로그인할 필요 없이 자동으로 새로운 액세스 토큰 발급 가능
  • 서버에서 세션을 관리하지 않고도 인증을 유지할 수 있음

1.1. 리프레시 토큰의 동작 방식

  1. 사용자가 로그인하면 액세스 토큰과 리프레시 토큰을 함께 발급한다.
  2. 클라이언트는 액세스 토큰을 사용하여 API 요청을 수행한다.
  3. 액세스 토큰이 만료되면 리프레시 토큰을 사용하여 새로운 액세스 토큰을 요청한다.
  4. 서버는 리프레시 토큰을 검증한 후 새로운 액세스 토큰을 발급한다.

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 인증 흐름

  1. 클라이언트(서드파티 애플리케이션)가 인증 서버에 인증 요청을 보냄
  2. 사용자가 로그인 및 권한 부여를 수행함
  3. 인증 서버가 인가 코드(Authorization Code)를 반환
  4. 클라이언트가 인가 코드를 이용해 액세스 토큰을 요청
  5. 인증 서버가 액세스 토큰을 발급하고 클라이언트가 이를 사용하여 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에 정리해뒀던 글을 블로그에 옮긴 글입니다.