Spring Security ‐ OAuth 2.0 Client Fundamentals - dnwls16071/Backend_Summary GitHub Wiki

📚 application.yml / OAuth2ClientProperties

클라이언트가 권한 부여 요청을 시작

  1. 클라이언트가 인가 서버로 권한 부여 요청을 하거나 토큰 요청을 할 경우 클라이언트 정보 및 엔드포인트 정보를 참조해서 전달한다.
  2. application.yml 환경설정 파일에 클라이언트 설정과 인가 서버 엔드포인트 설정을 한다.
  3. 초기화가 진행되면 application.yml에 있는 클라이언트 및 엔드 포인트 정보가 OAuth2ClientProperties의 각 속성에 바인딩이 된다.
  4. OAuth2ClientProperties에 바인딩된 속성의 값은 인가 서버로 권한 부여 요청을 하기 위한 ClientRegistration 클래스의 필드에 저장된다.
  5. OAuth2Client는 ClientRegistration을 참조해서 권한 부여 요청을 위한 매개변수를 구성하고 인가 서버와 통신한다.
server:
  port: 8081  # keycloak와 충돌하지 않도록 포트 변경

spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            clientId: oauth2-client-app                                           # 서비스 공급자에 등록된 클라이언트 아이디
            clientSecret: dXf021lMWuZ9kZafqxZn230MvVEdROIo                        # 서비스 공급자에 등록된 클라이언트 비밀번호
            clientName: oauth2-client-app                                         # 클라이언트 이름
            redirectUri: http://localhost:8081/login/oauth2/code/keycloak         # 인가 서버에서 권한 코드 부여 후 클라이언트로 리디렉션할 URI
            authorizationGrantType: authorization_code                            # OAuth 2.0 권한 부여 타입
            clientAuthenticationMethod: client_secret_basic                       # 클라이언트 자격증명 전송 방식
            scope: openid,profile,email                                           # 리소스 접근 제한 범위
        provider:
          keycloak:
            authorizationUri: http://localhost:8080/realms/oauth2/protocol/openid-connect/auth               # OAuth 2.0 권한 코드 부여 엔드포인트
            tokenUri: http://localhost:8080/realms/oauth2/protocol/openid-connect/token                      # OAuth 2.0 토큰 엔드 포인트
            issuerUri: http://localhost:8080/realms/oauth2                                                   # 서비스 공급자 위치
            userInfoUri: http://localhost:8080/realms/oauth2/protocol/openid-connect/userinfo                # OAuth 2.0 UserInfo 엔드 포인트
            jwkSetUri: http://localhost:8080/realms/oauth2/protocol/openid-connect/certs                     # OAuth 2.0 JwkSetUri 엔드 포인트
            userNameAttribute: preferred_username                                                            # OAuth 2.0 사용자명을 추출하는 클레임명

📚 ClientRegistration

  • OAuth 2.0 또는 OpenID Connect 1.0 Provider에서 클라이언트의 등록 정보를 나타낸다.
  • ClientRegistration은 OpenID Connect Provider 설정 엔드 포인트나 인가 서버의 메타데이터 엔드 포인트를 찾아 초기화할 수 있다.
  • ClientRegistration의 메서드를 사용하면 ClientRegistration을 설정할 수 있다.

각 내용 정리

  • registrationId : ClientRegistration을 식별할 수 있는 유니크한 ID
  • clientId : 클라이언트 식별자
  • clientSecret : 클라이언트 Secret
  • clientAuthenticationMethod : provider에서 클라이언트를 인증할 때 사용할 메서드로서 basic, post, none을 지원한다.
  • authorizationGrantType : OAuth 2.0 인가 프레임워크는 네 가지 권한 부여 타입을 정의하고 있으며 지원하는 값은 authorization_code, implicit, client_credentials, password이다.
  • redirectUriTemplate : 클라이언트에 등록한 리다이렉트 URL로, 사용자의 인증으로 클라이언트에 접근 권한을 부여하고 나면, 인가 서버가 이 URL로 최종 사용자의 브라우저를 리다이렉트시킨다.
  • Scopes : 인가 요청 플로우에서 클라이언트가 요청한 openid, 이메일, 프로필 등의 scope
  • clientName : 클라이언트를 나타내는 이름으로 자동 생성되는 로그인 페이지에서 노출하는 등에 사용한다.
  • authorizationUri : : 인가 서버의 인가 엔드포인트 URI.
  • tokenUri : 인가 서버의 토큰 엔드포인트 URI.
  • jwkSetUri : 인가 서버에서 JSON 웹 키 (JWK) 셋을 가져올 때 사용할 URI. 이 키 셋엔 ID 토큰의 JSON Web Signature (JWS) 를 검증할 때 사용할 암호키가 있으며, UserInfo 응답을 검증할 때도 사용할 수 있다
  • configurationMetadata : OpenID Provider 설정 정보로서 application.properties에 spring.security.oauth2.client.provider.[providerId].issuerUri를 설정했을 때만 사용할 수 있다.
  • (userInfoEndpoint)uri : 인증된 최종 사용자의 클레임/속성에 접근할 때 사용하는 UserInfo 엔드포인트 URI.
  • (userInfoEndPoint)authenticationMethod : UserInfo 엔드포인트로 액세스 토큰을 전송할 때 사용할 인증 메소드. header, form, query를 지원한다
  • userNameAttributeName : UserInfo 응답에 있는 속성 이름으로, 최종 사용자의 이름이나 식별자에 접근할 때 사용한다.
  • CommonOAuth2Provider 클래스의 일부이다.
  • OAuth 2.0 공급자 정보를 제공하는 클래스로서 글로벌 서비스 제공자 일부는 기본으로 제공된다.
  • Client ID나 Client Secret는 별도로 작성해야 한다.
  • Naver나 Kakao와 같은 국내 공급자 정보를 모든 항목을 수동으로 작성해야 한다.
  • 클라이언트 기준인 Registration 항목과 서비스 제공자 기준인 Provider 항목으로 구분해서 설정한다.
  • Java Config 방식으로 ClientRegistration을 등록할 수 있다.
  • ClientRegistration 객체를 생성할 수 있는 빌더 클래스를 반환한다.

📚 ClientRegistrationRepository

  • ClientRegistrationRepository는 OAuth 2.0 & OpenID Connect 1.0의 ClientRegistration 저장소 역할을 한다.
  • 클라이언트 등록 정보는 궁극적으로 인가 서버가 저장하고 관리하는데 이 레포지토리는 인가 서버에 일차적으로 저장된 클라이언트 등록 정보 일부를 검색하는 기능을 제공한다.
  • ClientRegistrationRepository의 디폴트 구현체는 InMemoryClientRegistrationRepository이다.
  • 자동 설정을 하게 되면 ClientRegistrationRepository도 ApplicationContext 내에 @Bean 어노테이션을 달아 스프링 빈으로의 등록이 필요하므로 필요하다면 원하는 곳에서 의존성을 주입할 수 있다.
@Component
public class CustomClientRegistrationRepository {

	@Bean
	public ClientRegistrationRepository clientRegistrationRepository() {
		return new InMemoryClientRegistrationRepository(this. keycloakClientRegistration());
	}

	private ClientRegistration keycloakClientRegistration() {
		return ClientRegistration.withRegistrationId("keycloak")
				.clientId("keycloak-client-id")
				.clientSecret("keycloak-client-secret")
				.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
				.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
				.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
				.scope("openid", "profile", "email", "address", "phone")
				.authorizationUri("http://localhost:8080/realms/oauth2")
				.tokenUri("http://localhost:8080/realms/oauth2/token")
				.userInfoUri("http://localhost:8080/realms/oauth2/userinfo")
				.userNameAttributeName(IdTokenClaimNames.SUB)
				.jwkSetUri("http://localhost:8080/realms/oauth2/certs")
				.clientName("Keycloak")
				.build();
	}
}

📚 자동설정에 의한 초기화