OpenID Connect 1.0은 id_token이라는 특별한 토큰을 제공함(ex. google)
이는 OAuth2 클라이언트(애플리케이션 서버 혹은 애플리케이션 서버에서 Oauth2 클라이언트 인증을 위해 사용하는 객체)가 사용자 신원 확인을 수행하고 사용자를 로그인시키는 기능을 제공함
OpenID Connet를 구현하지 않은 소셜 로그인 제공자의 경우도 OAuth2를 직접 사용해 사용자를 로그인시킬 수 있음
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// ...
.oauth2Login(Customizer.withDefaults());
return http.build();
}
}
위의 구성 외에도 애플리케이션에 적어도 하나의 ClientRegistration을 ClientRegstrationRepository
빈을 통해 구성해야 함
application.yml(Spring Boot 구성 속성 파일)을 다음과 같이 작성해서 InMemoryClientRegistrationRepository
빈을 구성할 수 있음.
spring:
security:
oauth2:
client:
registration:
my-oidc-client:
provider: my-oidc-provider
client-id: my-client-id
client-secret: my-client-secret
authorization-grant-type: authorization_code
scope: openid,profile
provider:
my-oidc-provider:
issuer-uri: https://my-oidc-provider.com
위의 구성을 통해 애플리케이션은 두 개의 추가 엔드포인트를 지원하게 된다.
로그인 엔드포인트 (예: /oauth2/authorization/my-oidc-client): 로그인을 시작하고 타사 인증 서버로 리디렉션을 수행
리디렉션 엔드포인트 (예: /login/oauth2/code/my-oidc-client): 인증 서버가 클라이언트 애플리케이션으로 리디렉션하는데 사용되며, 이 엔드포인트는 code 쿼리 파라미터를 통해 인증 코드를 받음
이를 통해 id_token 또는 access_token을 획득
위 구성에서 openid가 scope에 포함되어 있으면, OpenID Connect 1.0이 사용되어야 한다는 것을 의미한다.(구글은 OpenID Connect를 구현하였고, Spring Security와 Boot에서는 이런 OpenId Connect 제공자의 기본 설정을 미리 정의하고 있다. 따라서 구글 같은 경우에는 openid를 scope에 없어도 opneid를 secrutiy가 자동으로 추가함)
이때 Spring Security는 OIDC 전용 구성 요소(예: OidcUserService)를 요청 처리에 사용함.
openid가 scope에 없을 경우, Spring Security는 대신 OAuth2 전용 구성 요소(예: DefaultOAuth2UserService)를 사용함
OAuth2 클라이언트를 사용하는 이유는 OAuth2로 보호된 타사 API에 요청을 보내기 위함임
Oauth2AuthorizaedClient
는 Oauth2 인증을 통해 얻은 액세스 토큰과 그와 관련된 정보를 저장하고 관리하는 역할을 함.(즉, OAuth2 인증이 완료된 상태를 나타내는 클래스)
보호된 리소스에 접근하기 위해 요청을 보낼 때는 Authorization
헤더에 Bearer 토큰을 포함하여 요청을 보내야 함
Spring Security는 보호된 리소스에 접근하기 위해 액세스 토큰을 얻을 수 있는 OAuth2AuthorizedClientManager
구현체를 제공함
명시적으로 OAuth2AuthorizedClientManager
이 타입의 빈을 등록하지 않으면, 스프링 시큐리티가 빈으로 자동 등록
RestClient
혹은 WebClient
를 통해 api 요청을 하여 보호된 리소스에 접근한다.
Oauth2.0 client를 사용하기 위해 속성 정보를 application.yml에 입력
spring:
security:
oauth2:
client:
registration:
my-oauth2-client:
provider: my-auth-server
client-id: my-client-id
client-secret: my-client-secret
authorization-grant-type: authorization_code
scope: message.read,message.write
provider:
my-auth-server:
issuer-uri: https://my-auth-server.com
Spring Security에서 OAuth2 클라이언트 기능을 지원하도록 설정한 후, 보호된 리소스에 어떻게 접근할 것인지 결정하고 애플리케이션을 적절히 구성해야함
OAuth2 또는 OpenID Connect를 통해 사용자가 로그인하면, 인증 서버에서 보호된 리소스에 직접 접근할 수 있는 액세스 토큰을 제공함.
하나의 ClientRegistration만으로 사용자 로그인과 보호된 리소스에 접근 동시에 가능함.
로그인과 보호된 리소스에 접근에 대해 각각 다른 ClientRegistration
설정도 가능하지만, 기본적으로 하나를 사용함.
다음 예시는 애플리케이션이 OAuth2 클라이언트로서 작동하며, 사용자를 로그인시키고 타사 API에서 보호된 리소스를 요청하는 방법을 보여줍니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// ...
.oauth2Login(Customizer.withDefaults())
.oauth2Client(Customizer.withDefaults());
return http.build();
}
}
spring:
security:
oauth2:
client:
registration:
my-combined-client:
provider: my-auth-server
client-id: my-client-id
client-secret: my-client-secret
authorization-grant-type: authorization_code
scope: openid,profile,message.read,message.write
provider:
my-auth-server:
issuer-uri: https://my-auth-server.com
위에서 봤던 예시와 동일함
scope 속성에서 openid
, profile
과 같은 표준 범위와, message.read
, message.write
같은 사용자 정의 범위를 같이 사용할 수 있음