Spring Security Oauth 2.0 with facebook

수정이·2022년 8월 20일
0

security-jwt

목록 보기
3/7
post-thumbnail

Facebook 로그인

이번에는 Facebook을 사용하여 로그인을 해보자.
Facebook API 키와 비밀번호 얻는 것은 검색해서 알아보고, 코드에 집중하자.

먼저 설정을 해줘야 한다.
application 파일을 다음 코드를 추가해준다.

facebook:
  client-id: 2896863515994895
  client-secret: 0b1188709aae1c788b312221a2fd5f6c
  scope:
    - email
    - public_profile

지난번에 구글 로그인을 하기 위해 이것저것 코드를 추가하였다.
페이스북 로그인 역시 지난번에 추가한 코드를 거의 그대로 사용한다.

먼저 로그인 폼에 페이스북 로그인을 할 수 있도록 코드를 추가한다.
<a href="/oauth2/authorization/facebook">페이스북 로그인</a>
URI는 고정이다.

public class SecurityConfig {

    private final PrincipalOauth2UserService principalOauth2UserService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        		(생략)
                
                .defaultSuccessUrl("/")
                .and()
                .oauth2Login()
                .loginPage("/loginForm")
                .userInfoEndpoint()
                .userService(principalOauth2UserService);

        return http.build();
    }

SecurityConfig 클래스에서 OAuth 로그인을 할 수 있도록 설정하고, 소셜 로그인이 완료되면 후처리는 principalOauth2UserService 클래스에서 담당한다.

principalOauth2UserService 클래스에 OAuth 로그인의 후처리하는 코드가 있는데, 구글에서 제공하는 Attributes와 페이스북에서 제공하는 Attributes가 다르기 때문에 지난번 코드를 그대로 사용하면 DB에 제대로 저장이 되지 않는다.

그래서 다음에 다른 소셜로그인을 추가하여도 principalOauth2UserService 클래스의 코드를 수정하는 일이 없게 인터페이스를 생성하여 코드를 분리하도록 하자.

OAuth2UserInfo 인터페이스 추가

public interface OAuth2UserInfo {

    String getProviderId();
    String getProvider();
    String getEmail();
    String getName();
}

OAuth2UserInfo 인터페이스를 구현한 GoogleUserInfo 클래스 생성

public class GoogleUserInfo implements OAuth2UserInfo{

    private Map<String, Object> attributes;

    public GoogleUserInfo(Map<String, Object> attributes) {
        this.attributes = attributes;
    }

    @Override
    public String getProviderId() {
        return (String) attributes.get("sub");
    }

    @Override
    public String getProvider() {
        return "google";
    }

    @Override
    public String getEmail() {
        return (String) attributes.get("email");
    }

    @Override
    public String getName() {
        return (String) attributes.get("name");
    }
}

OAuth2UserInfo 인터페이스를 구현한 FacebookUserInfo 클래스 생성

public class FacebookUserInfo implements OAuth2UserInfo{

    private Map<String, Object> attributes;

    public FacebookUserInfo(Map<String, Object> attributes) {
        this.attributes = attributes;
    }

    @Override
    public String getProviderId() {
        return (String) attributes.get("id");
    }

    @Override
    public String getProvider() {
        return "facebook";
    }

    @Override
    public String getEmail() {
        return (String) attributes.get("email");
    }

    @Override
    public String getName() {
        return (String) attributes.get("name");
    }
}

위의 코드들을 보면 Attributes를 받아서 회원가입에 필요한 정보들을 반환하는 메소드들로 구성되어있다.

이제 다음은 PrincipalOauth2UserService 클래스에서 코드를 수정하자.

@Service
@RequiredArgsConstructor
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {

    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final UserRepository userRepository;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {

        OAuth2User oAuth2User = super.loadUser(userRequest);
        OAuth2UserInfo oAuth2UserInfo = null;

        if (userRequest.getClientRegistration().getRegistrationId().equals("google")) {
            System.out.println("구글 로그인 요청");
            oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes());
        } else if (userRequest.getClientRegistration().getRegistrationId().equals("facebook")) {
            System.out.println("페이스북 로그인 요청");
            oAuth2UserInfo = new FacebookUserInfo(oAuth2User.getAttributes());
        } else {
            System.out.println("우리는 구글과 페이스북만 지원한다.");
        }

        String provider = oAuth2UserInfo.getProvider();
        String providerId = oAuth2UserInfo.getProviderId();
        String username = provider + "_" + providerId;
        String password = bCryptPasswordEncoder.encode("겟인데어");
        String email = oAuth2UserInfo.getEmail();
        String role = "ROLE_USER";

        User userEntity = userRepository.findByUsername(username);

        if (userEntity == null) {
            userEntity = User.builder()
                    .username(username)
                    .password(password)
                    .email(email)
                    .role(role)
                    .provider(provider)
                    .providerId(providerId)
                    .build();
            userRepository.save(userEntity);
        }

        return new PrincipalDetails(userEntity, oAuth2User.getAttributes());
    }
}

userRequest.getClientRegistration().getRegistrationId()의 값이 "google"인지 "facebook"인지에 따라 생성되는 인스턴스가 달라진다.
생성된 인스턴스를 통해 회원의 정보가 입력되고 회원가입이 진행된다.
이로써 페이스북으로 로그인을 할 수 있다.


참고

스프링부트 시큐리티 & JWT 강의

0개의 댓글