스프링부트 oauth 소셜로그인(카카오, 네이버, 구글) 구현

2023. 2. 28. 17:41스프링

기본적으로 각 사이트에서  애플리케이션 등록 및 redirect url 설정은 다른 곳을 참고 하시고 시작하면 된다.

 

 일단 yml 파일에 설정을 등록해줘야 한다.

 

security:
  oauth2:
    client:
      registration:
        google:
          redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
          client-id: "my client-id"
          client-secret: "client-secret"
          scope:
            - email
            - profile
        naver:
          client-id: "my client-id"
          client-secret: "client-secret"
          redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
          authorization-grant-type: authorization_code
          scope:
            - email
            - name
            - mobile
          client-name: Naver
        kakao:
          client-id: "my client-id"
          redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
          client-authentication-method: POST
          authorization-grant-type: authorization_code
          scope: profile_nickname, account_email #동의 항목
          client-name: Kakao

      provider:
        naver:
          authorization-uri: https://nid.naver.com/oauth2.0/authorize
          token-uri: https://nid.naver.com/oauth2.0/token
          user-info-uri: https://openapi.naver.com/v1/nid/me
          user-name-attribute: response
        kakao:
          authorization-uri: https://kauth.kakao.com/oauth/authorize
          token-uri: https://kauth.kakao.com/oauth/token
          user-info-uri: https://kapi.kakao.com/v2/user/me
          user-name-attribute: id

client-id, client-secret은 본인이 받은 것들을 넣어주면 된다.

redirect url은 저 양식으로 통일해줘야 스프링부트에서 해당 url을 만들지 않고 한곳에서 처리가 가능하다.

예를 들어 카카오는 {본인 http://ip:port}/login/oauth2/code/kakao  이런식으로 사이트에 등록해야 처리가 가능하다.

카카오, 네이버는 따로 provider를 제공하지 않기 때문에 저렇게 yml에 설정해줘야 한다

@Configuration
@EnableWebSecurity
public class WebSecurityConfig{
   @Autowired
   private PrincipalOauth2UserService principalOauth2UserService;
   //HTTP 관련 인증 설정
   @Bean
   public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
      httpSecurity
      .csrf().disable().headers().frameOptions().disable()   //h2-console 화면 사용하기 위함
      .and()
         .authorizeRequests()
            .antMatchers("/**").permitAll()    //누구나 접근 가능
            .anyRequest().authenticated()  //나머지는 권한이 있기만 하면 접근 가능
      .and()
         .oauth2Login()
         .loginPage("/cetus/login")
            .successHandler((request, response, authentication) -> {
               response.sendRedirect("http://localhost:9095?oauth=true");
            })
            .userInfoEndpoint()
            .userService(principalOauth2UserService)
      ;

      return httpSecurity.build();
   }

}

.클라이언트에서 각각의 소셜로그인 redirectUrl을 호출하게 되면 이곳을 타게 되고 . 따로 구현한 principalOauth2UserService에  해당 정보들이 넘어오게 된다. 나 같은 경우 프론트와 서버를 분리해놔서 port까지 입력해줬다. 

 

@Service
@Slf4j
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {

 

    // 구글로부터 받은 userRequest 데이터에 대한 후처리되는 함수
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) {
        OAuth2User oauth2User = super.loadUser(userRequest);
        String provider = userRequest.getClientRegistration().getRegistrationId();
        Map<String, Object> userInfo = oauth2User.getAttributes();
        String username = "";
        String password = new BCryptPasswordEncoder().encode(UUID.randomUUID().toString());
        String email = "";

        switch (provider) {
            case "google":
                username = provider + "_" + userInfo.get("sub");
                email = (String) userInfo.get("email");
                break;

            case "naver":
                Map<String, Object> response = oauth2User.getAttribute("response");
                username = provider + "_" + response.get("id");
                email = (String) response.get("email");
                break;

            case "kakao":
                Map<String, Object> kakaoAccount = oauth2User.getAttribute("kakao_account");
                username = provider + "_" + userInfo.get("id");
                email = (String) kakaoAccount.get("email");
                break;
        }

      return super.loadUser(userRequest);

    }

DefaultOAtuh2UserService를 상속을 받고 loadUser라는 메소드에 해당 oauth 정보들이 모인다. 

여기서 후처리를 해주면 된다.

google과 naver와 kakao를 나눠 해당 정보를 저장한다.