위의 페이지에서 알아본 시큐리티의 동작 과정은 다음과 같다.

http.oauth2Login(oauth2 -> oauth2
			.redirectionEndpoint(redirection -> redirection.baseUri("/oauth2/callback/**"))
			.userInfoEndpoint(userInfo -> userInfo.userService(oauthUserService))
			.successHandler(oAuth2LoginSuccessHandler)
			.failureHandler(oAuth2LoginFailureHandler));

간단히 요약하자면 아래와 같다.

1. callback uri로 리소스 서버(ex. 구글)가 리다이렉트를 시킨다.
2. `userInfoEndpoint` 는 OAuth2 로그인 성공 후 사용자 정보를 가져올 때 설정을 담당한다. `userService`에 `OAuth2UserService` 인터페이스의 구현체를 등록하여 사용자 정보를 가져온다.
3. 위의 과정의 성공 실패에 따라 작동할 핸들러를 등록해준다.

흐름에 맞게 좀 더 자세히 알아보자!

  1. OAuth2UserService
@Service
@RequiredArgsConstructor
public class OauthUserService extends DefaultOAuth2UserService {

	private static final String ROLE_PREFIX = "ROLE_";

	private final UserCommandService oAuth2CommandService;

	@Override
	public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
		OAuth2User oAuth2User = super.loadUser(userRequest);
		Provider provider = extractProvider(userRequest);
		OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.createFor(provider, oAuth2User.getAttributes());

		User loginUser = oAuth2CommandService.login(oAuth2UserInfo.getEmail(), provider);
		oAuth2UserInfo.setUserId(loginUser.getId());

		return createOAuth2User(oAuth2UserInfo, loginUser);
	}

	private DefaultOAuth2User createOAuth2User(OAuth2UserInfo oAuth2UserInfo, User loginUser) {
		return new DefaultOAuth2User(
			Collections.singleton(
				new SimpleGrantedAuthority(ROLE_PREFIX.concat(loginUser.getRole().toString()))
			),
			oAuth2UserInfo.getAttributes(),
			oAuth2UserInfo.getOAuth2IdAttributeName()
		);
	}

	private Provider extractProvider(OAuth2UserRequest userRequest) {
		return Provider.from(
			userRequest
				.getClientRegistration()
				.getRegistrationId()
		);
	}
}
  1. 먼저 loadUser()가 실행되기 전에 이미 리소스 서버에 접근할 수 있는 액세스 토큰이 와있다…(띠용임) 그래서 OAuth2User oAuth2User = super.loadUser(userRequest) 만으로도 리소스 서버에서 원하는 정보들을 가지고 올 수 있다.

  2. 정보를 가져온다면 해당 정보에서 email 정보를 빼내어 사용자의 정보를 조회 혹은 저장한다. 그리고 user_id를 OAuth2UserInfo 에 넣어준다(해당 과정은 user_id를 SuccessHandler로 전달하기 위함이다)

  3. 여기서 이제 DefaultOAuth2User 를 반환해주어야 하는데 그 이유를 알기 위해선 Security Context에 대해 간단히 짚어야한다. Security Context는 우리가 아는 Application Context와 비슷하다고 생각할 수 있다. 한 인증 과정동안 한 Context를 공유한다고 생각할 수 있을거 같다.

이 Context를 통해 Authentication 객체를 공유하는데 해당 Authentication에 담기 위해 DefaultOAuth2User를 반환해야 한다.

  1. 이때, SimpleGrantedAuthority 를 통해 Role을 설정해주는데 “ROLE_”가 Prefix로 붙어있어야 Config 파일에서 hasRole()을 사용할 수 있다. 그런데 사실 우리 서비스에서는 사용하지 않기에 굳이 설정하지 않고 user_id처럼 추가해줘도 될 거 같긴하다. 고려할 부분은 사실 oAuth2UserInfo의 경우 우리 서비스가 아닌 리소스 서버의 정보들만 있는 것이 책임 분리에는 더 맞을 거 같단 점이다…( 2)과정이 좀 괜찮나 싶음 )