본문 바로가기
Develop/Spring

OAuth 2 샘플 애플리케이션 구현

by jaeyoungb 2022. 11. 28.

// 서버 측에서 HTML을 렌더링해주는 SSR(Sever Side Rendering) 방식의 애플리케이션 구현

 

- 의존성 추가

dependencies {
    ...
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    ...
}

 

- OAuth 2로 보호되는 .html 파일 생성 (뷰 생성)

 

- 뷰를 리턴하는 Controller를 생성

 

- application.yml 파일에 OAuth 2 클라이언트 등록 정보 추가

 

## 실무에서는 OAuth 2 클라이언트 ID와 Secret 같은 민감한 정보는 OS의 시스템 환경 변수에 설정하거나 애플리케이션 외부의 안전한 경로에 위치시키는 등의 방식을 사용해야 한다.

 

 

OAuth 2 인증을 위한 SecurityConfiguration 설정

 

1. Spring Boot의 자동 구성을 이용한 OAuth 2 인증 설정

  • 인증된 request에 대해서만 접근 허용 authorize.anyRequest().authenticated()
  • OAuth 2 로그인 인증 활성화 .oauth2Login(withDefaults())

2. Configuration을 통한 OAuth 2 인증 설정 - 자동 구성 방법과 달리 직접 Bean을 등록하는 방법

  • ClientRegistrationRepository를 Bean으로 등록 (ClientRegistrationRepository는 ClientRegistration을 저장하기 위한 Repository)
  • ClientRegistration 인스턴스를 생성하는 private 메서드 생성 - CommonOAuth2Provider enum 사용
  • 위 메서드를 호출해 ClientRegistration 인스턴스를 리턴 받고, ClientRegistrationRepository 인터페이스의 구현 클래스인 InMemoryClientRegistrationRepository의 인스턴스 생성 (메모리에 저장)

## ClientRegistration은 OAuth 2 시스템을 사용하는 Client 등록 정보를 표현하는 객체이다.

- https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/oauth2/client/registration/ClientRegistration.html

## Spring Security에서 제공하는 CommonOAuth2Provider enum은 내부적으로 Builder 패턴을 이용해 ClientRegistration 인스턴스를 제공한다.

- https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.html

- https://docs.spring.io/spring-security/reference/servlet/oauth2/login/core.html#oauth2login-common-oauth2-provider

 

## Spring Boot의 자동 구성을 이용한 방법은 상당히 편리하다. 하지만, 명시적으로 특정 설정을 선언해서 유지 보수에 용이하고 가독성 있는 코드를 구성하는 것 또한 중요하다.

 

 

인증된 Authentication 정보 확인

- SecurityContext에 인증된 Authentication이 저장되는 Spring Security의 특성을 이용해서 확인

 

1. SecurityContext를 이용하는 방법

  • 인증된 Authentication 객체를 통해 Principal 객체를 얻음
    (OAuth2User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()
  • 사용자의 이메일 정보를 얻음
    getAttributes().get("email"))

## OAuth 2 인증에 성공하기 전까지는 확인 불가

 

2. Authentication 객체를 핸들러 메서드 파라미터로 전달 받는 방법

  • 인증된 Authentication을 핸들러 메서드의 파라미터로 전달 받음

3. OAuth2User를 파라미터로 전달 받는 방법

  • @AuthenticationPrincipal 애너테이션을 이용해 OAuth2User 객체를 파라미터로 전달 받음

 

Authorization Server로부터 전달 받은 Access Token 확인

 

1. OAuth2AuthorizedClientService를 DI 받는 방법

  • OAuth2AuthorizedClientService를 이용해서 OAuth2AuthorizedClient가 보유하고 있는 Access Token에 접근할 수 있기 때문에, OAuth2AuthorizedClientService를 DI 받음
  • OAuth2AuthorizedClientRepository에서 OAuth2AuthorizedClient를 조회 loadAuthorizedClient()
  • OAuth2AccessToken 객체를 얻음 authorizedClient.getAccessToken()

2. OAuth2AuthorizedClient를 핸들러 메서드의 파라미터로 전달 받는 방법

  • @RegisteredOAuth2AuthorizedClient 애너테이션을 이용해 OAuth2AuthorizedClientRepository에 저장되어 있는 OAuthorizedClient를 파라미터로 전달 받음

## OAuth2AuthorizedClient가 Access Token을 보유하고 있고, OAuth2AuthorizedClientService를 이용해서 접근한다.

- https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/oauth2/client/OAuth2AuthorizedClient.html

- https://docs.spring.io/spring-security/reference/servlet/oauth2/client/core.html

 

## 하나 이상의 핸들러 메서드에서 OAuth2AuthorizedClient를 사용해야 된다면, OAuth2AuthorizedClientService를 DI 받아서 사용하는 것이 바람직하다.