OAuth / / 2024. 12. 17. 14:58

Spring Authorization Server 구성

1. OAuth2 Authorization Server란?

OAuth2 Authorization Server클라이언트 애플리케이션사용자 데이터에 접근할 수 있도록 액세스 토큰을 발급해 주는 서버입니다.
예를 들어, 사용자가 Google 로그인을 통해 특정 애플리케이션에 접근하는 경우, Google의 Authorization Server가 동작합니다.


1.1 핵심 개념

  1. Authorization Grant Type

    • 클라이언트가 사용자 데이터를 요청할 때 사용하는 방식입니다.
      • Authorization Code: 인증 코드 발급 후 액세스 토큰 발급 (가장 많이 사용)
      • Client Credentials: 서버 간 통신 시 사용
      • Password Grant (Deprecated): 사용자 이름과 비밀번호를 직접 전달 (보안 취약)
  2. JWT (JSON Web Token)

    • 인증 및 권한 부여 정보를 포함하는 JSON 기반 토큰입니다.
    • 클라이언트는 이 토큰을 통해 인증된 사용자임을 증명합니다.
    • 서명을 통해 위변조를 방지합니다.
  3. JWK (JSON Web Key)

    • JWT 서명에 사용하는 공개 키비밀 키를 JSON 형식으로 표현한 키입니다.
  4. OIDC (OpenID Connect)

    • OAuth2를 확장한 표준으로, 사용자 ID 정보를 포함합니다.
    • 예: scope=openid를 통해 사용자 정보를 요청합니다.

2. SecurityConfig 코드 분석

2.1 OAuth2 인증 서버 필터 체인

@Bean
@Order(1)
public SecurityFilterChain asFilterChain(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

    http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
        .oidc(Customizer.withDefaults());

    http.exceptionHandling(e ->
            e.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
    );

    return http.build();
}

설명

  1. OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)

    • Spring이 제공하는 OAuth2 Authorization Server의 기본 보안 설정을 적용합니다.
    • CSRF 보호, 세션 관리, 권한 검사 등의 보안을 설정합니다.
  2. OIDC 지원

    • .oidc(Customizer.withDefaults()): OpenID Connect를 활성화합니다.
    • 클라이언트는 scope=openid를 통해 사용자 ID 정보를 요청할 수 있습니다.
  3. 예외 처리

    • 인증되지 않은 요청이 들어오면 /login 페이지로 리디렉션합니다.

2.2 기본 로그인 필터 체인

@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
    http.formLogin(Customizer.withDefaults());

    http.authorizeHttpRequests(c -> c.anyRequest().authenticated());

    return http.build();
}

설명

  • 폼 로그인: 사용자가 기본 로그인 폼을 통해 인증합니다.
  • 모든 요청 인증 필수:
    • anyRequest().authenticated()를 통해 모든 요청에 대해 인증을 요구합니다.

2.3 사용자 인증 정보 설정

@Bean
public UserDetailsService userDetailsService() {
    UserDetails userDetails = User.withUsername("bill")
        .password("password")
        .roles("USER")
        .build();

    return new InMemoryUserDetailsManager(userDetails);
}

@Bean
public PasswordEncoder passwordEncoder() {
    return NoOpPasswordEncoder.getInstance();
}

설명

  1. UserDetailsService

    • 인메모리에 bill이라는 사용자 계정을 생성합니다.
    • 아이디: bill
    • 비밀번호: password
    • 역할: USER
  2. 비밀번호 인코더

    • NoOpPasswordEncoder암호화 없이 비밀번호를 사용합니다.
    • 테스트용이며, 실제 운영에서는 BCrypt와 같은 안전한 방식 사용이 필요합니다.

2.4 클라이언트 등록 설정

@Bean
public RegisteredClientRepository registeredClientRepository() {
    RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
        .clientId("client")
        .clientSecret("secret")
        .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
        .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
        .redirectUri("https://www.manning.com/authorized")
        .scope(OidcScopes.OPENID)
        .build();

    return new InMemoryRegisteredClientRepository(registeredClient);
}

설명

  1. RegisteredClient

    • OAuth2 클라이언트를 설정합니다.
      • Client ID: 클라이언트를 식별하는 값 (client)
      • Client Secret: 클라이언트 인증을 위한 비밀번호 (secret)
      • Grant Type: AUTHORIZATION_CODE
      • Redirect URI: 인증 완료 후 리디렉션할 주소
  2. RegisteredClientRepository

    • InMemoryRegisteredClientRepository를 사용해 클라이언트 정보를 메모리에 저장합니다.

2.5 RSA 키 쌍 생성 및 JWK 설정

@Bean
public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();

    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

    RSAKey rsaKey = new RSAKey.Builder(publicKey)
        .privateKey(privateKey)
        .keyID(UUID.randomUUID().toString())
        .build();

    JWKSet jwkSet = new JWKSet(rsaKey);
    return new ImmutableJWKSet<>(jwkSet);
}

설명

  1. RSA 키 쌍 생성
    • KeyPairGenerator를 사용해 2048비트 RSA 키 쌍을 생성합니다.
  2. JWK 생성
    • RSA 키를 JWK (JSON Web Key) 형식으로 변환합니다.
  3. ImmutableJWKSet
    • JWT 서명에 사용할 키를 JWK 소스로 반환합니다.

2.6 JWT 커스터마이징

@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
    return context -> {
        JwtClaimsSet.Builder claims = context.getClaims();
        claims.claim("priority", "HIGH");
    };
}

설명

  • OAuth2TokenCustomizer: JWT에 커스텀 클레임을 추가합니다.
  • 예시로 "priority": "HIGH"라는 클레임을 추가하여 특정 사용자 정보를 전달할 수 있습니다.

3. 결론 및 요약

SecurityConfig 클래스는 Spring Authorization Server를 기반으로 OAuth2 인증 서버를 설정하는 예제입니다.

핵심 기능 요약

  1. OAuth2 Authorization Server

    • 인증 및 액세스 토큰 발급을 처리합니다.
  2. OIDC (OpenID Connect)

    • 사용자 ID 정보 제공 (scope=openid).
  3. JWT 커스터마이징

    • JWT에 추가적인 클레임 값을 넣습니다.
  4. RSA 키 관리

    • JWT 서명 및 검증을 위한 RSA 키 쌍을 생성하고 JWK 형식으로 설정합니다.

이 설정은 OAuth2OIDC 기반의 인증 서버를 구현하는 데 기초적인 예제를 제공합니다. 추가적으로 보안 강화를 위해 비밀번호 암호화 및 외부 저장소 사용을 고려할 수 있습니다.

'OAuth' 카테고리의 다른 글

Client Credentials Grant Type  (0) 2024.12.18
OAuth 2.0 액세스 토큰 발급 방법  (0) 2024.12.17
Authorization Code  (0) 2024.12.17
Proof Key(PKCE)  (0) 2024.12.17
투명 토큰(Transparent Token)과 불투명 토큰(Opaque Token)  (1) 2024.12.17
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유