본문 바로가기

1.프로그래밍/Java

[Spring Security] Spring Security OAuth2.0 Flow

728x90
반응형

OAuth 2.0 (OpenID Authentication)

OAuth (OpenID Authentication) 란, 타사의 사이트에 대한 접근 권한을 얻고 그 권한을 이용하여 개발할 수 있도록 도와주는 프레임워크다. 구글, 카카오, 네이버 등과 같은 사이트에서 로그인을 하면 직접 구현한 사이트에서도 로그인 인증을 받을 수 있도록 되는 구조다.


물론 구글에서 로그인을 했다고 해서, 개발한 웹 사이트에 구글 ID와 PW를 그대로 전달해주면 안되므로, Access Token을 발급 받고, 그 토큰을 기반으로 원하는 기능을 구현해야 한다.


Access Token은 로그인을 하지 않고 인증을 할 수 있도록 해주는 인증 토큰 정도의 개념이다. 유저 A가 직접 개발한 웹 사이트 X에서 자신의 구글 캘린더에 대한 접근을 허용해 준다면, Access Token을 통해 해당 정보 권한을 받아올 수 있어서 그 정보를 토대로 캘린더에 글을 작성하고 삭제하는 등의 작업을 할 수 있게 된다.


여기서 Access Token을 발급 받기 위한 일련의 과정들을 인터페이스로 정의해둔 것이 바로 OAuth 다. OAuth에서 중요한 용어는 크게 세 가지다.


  • Resource Owner: 개인 정보의 소유자를 가리킨다. 유저 A가 이에 해당한다.
  • Client: 제 3의 서비스로부터 인증을 받고자 하는 서버다. 직접 개발한 웹 사이트 X가 이에 해당한다.
  • Resource Server: 개인 정보를 저장하고 있는 서버를 의미한다. 구글이 이에 해당한다.

유저 A가 구글에서 제공해주는 서비스를 이용하는 셈이므로 타 사의 서비스를 이용하기 위해서는 신청을 해야 한다. 신청 방법은 구글, 카카오, 네이버, 페이스북 등 각각 모두 방식이 다르지만, 반드시 필요로 하는 내용은 ID, PW, 본인 인증 방법 이렇게 세 가지 정도다. 각 사이트의 개발자 Docs를 참고하면 쉽게 등록하고 발급받을 수 있다.


  • Client ID: Resource Server에서 발급해주는 ID. 웹 사이트 X에 구글이 할당한 ID를 알려주는 것이다.
  • Client Secret: Resource Server에서 발급해주는 PW. 웹 사이트 X에 구글이 할당한 PW를 알려주는 것이다.
  • Authorized Redirect Uri: Client 측에서 등록하는 Url. 만약 이 Uri로부터 인증을 요구하는 것이 아니라면, Resource Server는 해당 요청을 무시한다.

Spring Security Oauth2 처리 플로우

OAuth2ClientProperties

Spring Security 는 설정파일 (.properties, .yml)에 적어둔 정보들을 통해 실행시 OAuth2ClientProperties 를 만든다.

OAuth2ClientPropertiesInitializingBean을 구현하고 있고, 애플리케이션 실행 시 @ConfigurationProperties를 통해 주입받아서 해당 데이터들을 Map으로 매핑해서 갖고 있는다.

InMemoryRepository

Spring Security는 애플리케이션 실행 시 OAuth2ClientProperties@Bean으로 등록 해둔다.

그리고 OAuth2ClientProperties의 내부 값들을 통해 ClientRegistration (clientId, clientSecret 등의 정보를 담는 객체)를 만들어 각각 InMemoryRepository에 저장한다.

이러한 과정들이 OAuth2ClientPropertiesRegistrationAdapter에서 진행된다.

해당 코드의 흐름은 OAuth2ClientRegistrationRepositoryConfiguration -> OAuth2ClientPropertiesRegistrationAdapter 으로 보면 된다.

OAuth2ClientPropertiesRegistrationAdapter

OAuth2ClientPropertiesRegistrationAdapter 안에서 getCommonProvider() 라는 메서드가 존재하는데,

이 메서드는 ClientRegistration에서 설정 파일에 등록한 providerId(google, facebook, github) 등을 통해 Spring Security에서 자주 사용되어

CommonOAuth2Provider 라는 Enum 클래스에 등록해놓은 정보들을 가져와서 사용한다.

그래서, CommonOAuth2Provider에 등록되지 않은 Oauth Server에 경우 더 많은 설정이 추가되어야 한다.

이러한 과정들을 거쳐서 설정파일에 작성한 정보들을 토대로 ClientRegistration이 생성되고

ClientRegistration 객체를 Map으로 담아 InMemoryClientRegistrationRepository에 저장해두고 사용하는 것이다.

OAuth2AuthorizationRequestRedirectFilter

Spring SecurityFilter Chain 중 하나로서 /oauth2/authorization/{registrationId} 로 들어온 요청을 처리하는 필터이다.

해당 필터는 내부의 OAuth2AuthorizationRequestResolver 라는 클래스로 OAuth2 로그인 요청을 위임한다.

OAuth2AuthorizationRequestResolver 는 위의 Uri 요청에서 registrationId를 추출하여,

위의 InMemoryRepository에 등록해놓은 Map<String, ClientRegistration> 을 통해서 ClientRegistration 객체를 가져온다.

해당 ClientRegistration 객체를 통해 OAuth2AuthorizationRequest 해당 객체를 만들어, 객체 안에 있는 redirectUri로 요청을 보낸다.

그렇게 하면 이제 아이디 / 비밀번호를 입력하는 창이 나오게 된다.

OAuth2LoginAuthenticationFilter

아이디 / 비밀번호를 입력한 후 에는 해당 OAuth2LoginAuthenticationFilter가 작동한다.

아이디 / 비밀번호가 OAuth Server의 정보와 일치하게 된다면,

해당 정보를 통해 OAuth2AuthorizationResponse 라는 녀석을 생성하고 OAuth Server가 주는 AccessToekn 을 갖고온다.

이때, 내부적으로 OAuth2LoginAuthenticationProvider.getAccessToken() 이라는 메서드를 호출하여 갖고오는 담당을 한다.

그 이후 가져온 AccessToken을 통해 유저정보를 가져오게 되는데,
그 역할은 OAuh2UserService라는 인터페이스를 구현하고 있는 DefaultOAuth2UserService 에서 진행되고, .loadUser()라는 메서드를 통해 이루어진다.

728x90
반응형