[java] Spring Framework를 사용하여 OAuth 인증 구현하기

OAuth는 웹 애플리케이션, 모바일 앱 등에서 외부 서비스의 사용자 인증과 권한 부여를 처리하기 위한 개방형 표준 프로토콜입니다. Spring Framework를 사용하여 OAuth 인증을 구현하는 방법에 대해 알아보겠습니다.

1. Maven 의존성 추가

OAuth 인증을 구현하기 위해 먼저 Maven 또는 Gradle 등의 의존성 관리 도구를 사용하여 Spring Security OAuth2 모듈을 추가해야 합니다. pom.xml 파일에 다음과 같이 의존성을 추가합니다.

<dependencies>
  <!-- Spring Security OAuth2 -->
  <dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.5.0.RELEASE</version>
  </dependency>
</dependencies>

2. OAuth2 구성하기

Spring Security OAuth2를 사용하여 OAuth 인증을 구현하기 위해 몇 가지 설정이 필요합니다. WebSecurityConfigurerAdapter를 상속받은 구성 클래스를 생성하여 다음과 같이 설정합니다.

@Configuration
@EnableWebSecurity
public class OAuth2Config extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
        .antMatchers("/**").permitAll()
        .anyRequest().authenticated()
        .and()
      .oauth2Login();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    // 사용자 인증 관련 설정 추가
  }

  @Bean
  public OAuth2UserService<OAuth2UserRequest, OAuth2User> userService() {
    // OAuth2 사용자 서비스 설정
  }
}

위의 예시에서는 모든 요청에 대해 인증을 요구하고 있지만, 필요에 따라 URL 패턴을 세분화하여 설정할 수 있습니다.

3. 사용자 인증 관련 설정 추가

위의 예시에서 configure(AuthenticationManagerBuilder auth) 메소드를 오버라이딩하여 사용자 인증 관련 설정을 추가해야 합니다. 예를 들어, 인메모리 사용자 스토어를 사용하여 사용자를 인증하고, 기본 사용자 데이터베이스를 사용하는 경우 다음과 같이 설정할 수 있습니다.

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  auth.inMemoryAuthentication()
    .withUser("admin").password("{noop}admin").roles("ADMIN")
    .and()
    .withUser("user").password("{noop}user").roles("USER");
}

위의 예시에서 {noop}은 인코딩되지 않은 평문(plain text) 암호임을 나타냅니다.

4. OAuth2 사용자 서비스 설정

userService() 메소드를 오버라이딩하여 OAuth2 사용자 서비스를 설정해야 합니다. 이 메소드에서는 외부 OAuth 서비스 제공자로부터 제공받은 인증 정보를 기반으로 사용자 정보를 가져오는 작업을 수행합니다. 예를 들어, Google OAuth2를 사용하는 경우 다음과 같이 설정할 수 있습니다.

@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> userService() {
  OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
  return new CustomOAuth2UserService(delegate);
}

public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {

  private OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate;

  public CustomOAuth2UserService(OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate) {
    this.delegate = delegate;
  }

  @Override
  public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
    OAuth2User user = delegate.loadUser(userRequest);
    // 사용자 정보 가져오기 및 저장
    return user;
  }
}

위의 예시에서 CustomOAuth2UserService 클래스는 DefaultOAuth2UserService를 래핑하여 사용자 정보를 가져오는 작업을 수행합니다.

5. OAuth2 인증 흐름 구현하기

먼저, 외부 OAuth 서비스 제공자(예: Google, Facebook 등)에 애플리케이션을 등록해야 합니다. 등록 후에는 클라이언트 ID와 클라이언트 시크릿을 발급받을 수 있습니다.

인증 흐름은 다음과 같습니다.

  1. 사용자는 애플리케이션에 접속하여 외부 OAuth 제공자로 로그인을 요청합니다.
  2. 애플리케이션은 클라이언트 ID와 리다이렉트 URI를 사용하여 외부 OAuth 제공자로 리다이렉트합니다.
  3. 사용자는 외부 OAuth 제공자에 로그인한 후 권한을 승인합니다.
  4. 외부 OAuth 제공자는 승인한 권한을 애플리케이션의 리다이렉트 URI로 전달합니다.
  5. 애플리케이션은 전달받은 인증 정보를 사용하여 사용자를 인증하고, 인증된 사용자 정보를 세션에 저장합니다.

이와 같은 OAuth2 인증 흐름은 Spring Framework에서 자동으로 처리할 수 있습니다. 설정 파일 및 코드를 통해 클라이언트 ID, 클라이언트 시크릿, 리다이렉트 URI 등의 정보를 설정하고, OAuth2 인증을 처리하는 컨트롤러를 작성하면 됩니다.

참고 자료