본문 바로가기
3th Party Util

Spring에서 카카오 로그인 사용하기 - Spring Security 5, OAuth 2 - deprecated 대응 2023년 6월 27일

by kakao-TAM 2021. 1. 27.

OAuth2의 이해

oauth.net/2/

 

OAuth 2.0 — OAuth

OAuth 2.0 OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices. This

oauth.net

OAuth 2.0은 인증을 위한 업계 표준 프로토콜로 클라이언트 개발자의 단순성에 초점을 맞추면서 다양한 장치에 대한 특정 인증 흐름을 제공합니다. 이 사양은 2012년 10월 IETF OAuth 워킹 그룹 내에서 개발되었습니다.

<OAuth2 인증 흐름>

OAuth 2 인증 흐름은 리소스 소유자에게 인가 요청을 하여 인가 Code를 받고, 인가 Code를 이용하여 인증 서버에서 액세스 토큰을 받은 후, 액세스 토큰을 이용하여 자원 서버에서 필요한 리소스를 조회하는 간단한 개념입니다. 

* Spring Social의 지원 종료 
Spring Security 5가 출시됨(2018년 03월 06일)에 따라 기존에 사용하던 Spring Social은 
Spring Security의 일부가되었습니다. Spring Social은 2019년 7월 3일에 종료되었습니다.

* WebSecurityConfigurerAdapter의 Deprecated (2022년 2월 21일)
https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter
Spring Security 5.7.0-M2에서는 사용자가 구성 요소 기반 보안 구성으로 이동하도록 권장하므로 더 이상 사용되지 않습니다

카카오 디벨로퍼스의 로그인 설정은 가이드를 참고하여 먼저 설정합니다. 

Spring Security 5에서 OAuth2 사용하기

SpringToolSuite4 또는 VisualStudio Code의 플러그인을 설치하여 Spring Stater Project 기능을 이용해서 프로젝트를 생성합니다. spring.io/tools

File > New > Spring Starter Project

java 소스 코드 폴더에 SecurityConfig.java 파일과 KakaoOAuth2UserService.java 파일

resources 폴더에 application.yml 파일을 생성합니다.

Spring Tools 4 for Visual Studio Code Spring Tools 4 for Eclipse



▶ application.yml

https://docs.spring.io/spring-security/reference/servlet/appendix/namespace/http.html#nsa-client-registration-attributes

spring:
  security:
    oauth2:
      client:
        registration:
          kakao:
            authorization-grant-type: authorization_code
            client-id: 444444444444444479e933556a21e8
            client-secret: QQQQQQQQQQQQQQQQuOfOLzjZMc5q1U
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
            scope:
              - profile
              - account_email
            client-authentication-method: client_secret_post
            client-name: Kakao

        provider:
         
          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에는 REST-API-KEY를 세팅합니다.

@RequiredArgsConstructor 어노테이션 사용을 위해 build.gradle파일에 annotationProcessor도 추가합니다.

annotationProcessor 'org.projectlombok:lombok'

 

▶ SecurityConfig.java

- WebSecurityConfigurerAdapter가 deprecate되어 SecurityFilterChain 기반 코드로 변경합니다. 

- authorizeHttpRequests 의 자세한 사용 방법은 Spring 기술문서를 참고 바랍니다.

https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html

package com.example.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import static org.springframework.security.config.Customizer.withDefaults;
import lombok.RequiredArgsConstructor;

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig {
    private final KakaoOAuth2UserService kakaoOAuth2UserService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(withDefaults())
                .cors(withDefaults())
                .authorizeHttpRequests(request -> request
                        .requestMatchers("/index.html",
                                "/images/**",
                                "/permitAllConents.html")
                        .permitAll()
                        .requestMatchers("/user").hasRole("USER")
                        .anyRequest().authenticated())
                .oauth2Login(oauth2 -> oauth2.userInfoEndpoint(userInfo -> userInfo
                        .userService(kakaoOAuth2UserService)))
                .logout(withDefaults());
        return http.build();
    }
}

KakaoOAuth2UserService.java

package com.example.demo;

import java.util.Collections;
import java.util.Map;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequiredArgsConstructor
@Service
public class KakaoOAuth2UserService extends DefaultOAuth2UserService {

    private final HttpSession httpSession;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);
        Map<String, Object> attributes = oAuth2User.getAttributes();

        log.info("attributes :: " + attributes);

        httpSession.setAttribute("login_info", attributes);

        return new DefaultOAuth2User(Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")),
                oAuth2User.getAttributes(), "id");
    }
}

* Spring Security5를 이용하여 카카오 로그인 OAuth2를 구현하기 위한 가장 간단한 소스코드를 위해 많은 부분을 생략 하고 인증 부분만 구현 하였습니다. Spring을 구동하여 http://localhost:8080/login 으로 접근하면 Default 로그인 페이지가 표시됩니다.

* SecurityFilterChain 내 authorizeHttpRequests의 requestMatchers 설정으로 별도 로그인 페이지를 두고 http://localhost:8080/oauth2/authorization/kakao 를 호출하면 스프링을 거쳐 카카오에 인가코드 요청하고 리다이렉트 URI로 돌아와 액세스 토큰 발급 및 사용자 정보조회가지 OAuth2 Client에서 처리합니다.  

링크는 application.yml에 정의된 authorization-uri에 다음과 같이 파라메터를 구성하여 세팅됩니다.

kakao에서 로그인 이후 호출된 CallBack URI에서 리턴받은 code를 이용하여 토큰 요청을 하고 받은 토큰을 이용하여 DefaultOAuth2UserService를 상속받은 KakaoOAuth2UserService의 loadUser 함수 호출로 프로필 정보를 조회합니다.

 

로그인 성공 이후 리다이렉트 페이지를 구성하지 않았지만, loadUser에서 Console 로그 출력으로 프로필을 정상적으로 조회 했음을 확인할 수 있습니다. 

 

 

댓글