OAuth - OAuth2User, OAuth2UserService

TopOfTheHead·2026년 5월 24일

Spring OAuth

목록 보기
6/11

OAuth2User
OAuthUserDetails 역할을 수행하는 Spring Security Core Interface

OAuth Client가 요청한 사용자정보에 대해 OAuth Provider에서 응답한 사용자정보를 포항한 Oauth2User 생성
▶ 기존 DB에서 저장된 사용자정보를 가져와서 생성되는 UserDetails와 차이가 존재

OAuth2UserServiceloadUser(OAuth2UserRequest userRequest)에 의해 생성

  • 커스텀 OAuth2User 구현체 정의
    @Getter를 통해 구현메서드 : email / name / attributesgetter를 축약

    DTO로서의 필드OAuth Provider에서 제공되는 사용자정보에 해당하는 필드( attributes )를 정의해야한다.
@Accessors(chain = true)
@Getter
public class CurretUser implements OAuth2User {
    private String email;
    private String name;
    private Map<String,Object> attributes;
    @Setter
    private String role;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return List.of(
                new SimpleGrantedAuthority(role)
        );
    }
    @Builder
    public CurretUser(String email, String name, Map<String, Object> attributes){
        this.email = email;
        this.name = name;
        this.attributes = attributes;
    }
	public static CurrentUser from(CurretUser user){
        if(user == null) throw new IllegalArgumentException("MEMBER_NOT_FOUND");
        return CurrentUser.builder()
                .name(user.getName())
                .email(user.getEmail())
                .build()
                // MemberDetails 내 @Accessor 을 통해
                // setter에서 객체를 반환하도록 설정.
                .setId(user.getId())
                .setRole(user.getRole());
    }
}
  • attributes :
    OAuth ProvicerResource Server에서 반환한 사용자정보 데이터를 저장하는 Map 자료구조 field
    Map <Key,Value> 객체로 반환

    ex ) OAuth Provider : Goole인 경우 클라이언트에서 사용자정보이름, 이메일에 대해 권한을 부여받은 경우 사용자 정보는 다음처럼 반환.
{
  "sub": "123456",
  "email": "test@gmail.com",
  "name": "kim"
}

Map 객체에서 Map객체.get("key명")을 통해 가져와서 활용

OAuth2UserService :
OAuth 2.0UserDetailsService 역할을 수행하는 인터페이스

권한부여승인코드를 통해 획득한 Access Token을 통해 OAuth Provider요청OAuth Provider에서 전달된 사용자 정보를 기반으로 UserDetails 구현체를 생성하는 역할을 수행
서비스 계층에서 구현클래스 : DefaultOAuth2UserService상속하여 loadUser()를 통해 해당 작업을 수행

DefaultOAuth2UserService
OAuth2UserService 기반의 구현 클래스
▶ 실제로 OAuth Provider에서 전달된 사용자 정보를 기반으로 UserDetails 구현체를 생성하는 역할을 수행

  • loadUser(OAuth2UserRequest userRequest)
    OAuth Provider에서 제공된 사용자정보를 조회하고 OAuth2User를 생성 및 반환하는 구현메서드
    UserDetailsService.loadUserByUsername("username") 역할을 수행

loadUser()를 활용한 권한부여승인코드 요청 / 응답 과정

loadUser()가 호출되기 이전 권한부여승인코드 상 1 ~ 6번 과정이 수행되어있음.
OAuth2UserRequest에 포함된 Access Token을 활용하여 7번 과정을 시작

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberService extends DefaultOAuth2UserService {
    private final MemberRepository memberRepository;
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        // ~ 권한부여승인코드 상 1 ~ 6번이 자동으로 수행
        //
        // 권한부여승인코드 7 ~ 8번  
        // OAuth2UserRequest의 Access Token, ClientRegistration을 기반으로
        // OAuth Provider에게 요청 및 반환받은 사용자정보를 기반으로 UserDetails 구현체 생성
        OAuth2User oAuth2User = super.loadUser(userRequest);
        //
        // 반환받은 사용자정보를 활용하여 회원가입을 수행하는 로직 정의
        //
        return oAuth2User;
    }
}

super.loadUser(userRequest);이 수행된 이후 응답받은 사용자정보를 포함하는 OAuthUser 구현체를 기반으로 회원가입 등의 로직을 수행
응답받은 사용자정보는 해당 메서드에서 반환된 OAuthUser 구현체Map<K,V>의 attributes 필드에 포함

회원개인정보를 더 요구하기 위해서는 OAuth Provider에게 추가적으로 자원에 대한 권한을 추가적으로 요청

  • OAuth2User oAuth2User = super.loadUser(userRequest);
    loadUser() 메서드 내에서 OAuth2UserRequest부모클래스 : DefaultOAuth2UserService에 전달함으로써 OAuth2UserRequest 내 포함된 AccessTokenOAuth Provider 정보를 기반으로 OAuth Provider요청 및 수신받은 사용자정보를 포함한 OAuth2User 구현체를 반환
    권한부여승인코드 7 ~ 8번 과정에 해당

OAuth2UserRequest
OAuth Provider사용자정보요청하기 위한 요청 객체
▶ 내부에 Access Token, ClientRegistration 등의 OAuth 로그인 시 필요한 정보를 포함

  • OAuth2AccessToken
    권한부여승인코드를 송신하여 획득한 Access Token
    OAuth2UserRequest객체.getAccessToken()를 통해 획득 가능

  • ClientRegistration
    application.yml 내 정의한 OAuth Client / Provider를 포함하는 객체
    client-id, client-secret, provider 정보, redirect-uri, scope

    OAuth2UserRequest객체.getClientRegistration()를 통해 획득 가능
    • ClientRegistration객체.getRegistrationId()
      Provider 정보반환
      ex ) kakao, google, ...
profile
공부기록 블로그

0개의 댓글