GitHub

https://github.com/Backcoder-June

BackCoder 기록 그리고 숙달

Back to the Spring

[ Spring Security ] OAuth2 구글 / 네이버 로그인

Backcoder 2022. 12. 23. 22:55

너무나 다양하고 많은 웹 / 앱 서비스들이 출시되고 있는 추세에

매번 새로운 Application 에, 새로운 정보로 가입하는 건 요즘은 꽤나 기피됩니다. 

 

OAuth2 를 활용하면

대중적인 사이트들의 로그인 API 를 활용해서 나의 새로운 Application에 손쉽게 클릭 한 두번으로 가입할 수 있게 됩니다. 

 

최근 출시하는 Application 들은 이러한 편의성을 강점으로 살리고자 로그인 방법만 10가지가 넘게 제공하기도 하죠..

대표적인 사이트 구글, 네이버 로그인을 OAuth 를 활용해 적용하는 법을 정리해 보았습니다. 

 

 

1. 라이브러리 설치 

[ Build Gradle ] 
# Spring Scurity     
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
OAuth2 - Client
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
# Spring Boot - DevTools
developmentOnly 'org.springframework.boot:spring-boot-devtools'




2. application-oauth.properties 생성 ( new - resource bundle ) 

 

(1) 구글 
spring.security.oauth2.client.registration.google.client-id=
spring.security.oauth2.client.registration.google.client-secret=
spring.security.oauth2.client.registration.google.scope=email

 

(2) 네이버 

#registration
spring.security.oauth2.client.registration.naver.client-id=
spring.security.oauth2.client.registration.naver.client-secret=
spring.security.oauth2.client.registration.naver.redirect-uri={baseUrl}/{action}/oauth2/code/{registrationId}
spring.security.oauth2.client.registration.naver.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.naver.scope=email
spring.security.oauth2.client.registration.naver.client-name=Naver

# provider
spring.security.oauth2.client.provider.naver.authorization-uri=https://nid.naver.com/oauth2.0/authorize
spring.security.oauth2.client.provider.naver.token-uri=https://nid.naver.com/oauth2.0/token
spring.security.oauth2.client.provider.naver.user-info-uri=https://openapi.naver.com/v1/nid/me
spring.security.oauth2.client.provider.naver.user-name-attribute=response

 

=> application.properties 에 가져오기

[ application.properties ]
# 추가 
spring.profiles.include=oauth


- 구글/네이버 클라이언트 id, pw 가 들어가므로, gitIgnore, 암호화 등 조치 필요 
- scope : 구글/네이버 로그인 시 사이트에서 받아올 정보 종류. 

 

 

3. SecurityConfig 설정 추가 

(1) 기존 security configure 설정에 oauth2 설정을 추가 

@Override
    protected void configure(HttpSecurity http) throws Exception{

(기존 설정) ...           

.and()
                .oauth2Login().loginPage("/login")
                .defaultSuccessUrl("/test")
                .userInfoEndpoint()
                .userService(customOAuth2UserService);

}

 

=> OAuth2 로그인 페이지 설정, success fail URL 등 설정 

=> customOAuth2UserService 에서 처리하겠다. 

( OAuth가 아닌, 자체 로그인에 대한 처리는 UserDetailService 인터페이스를 상속해 처리했었다. ) 

 

 

(2) Security Config 에서 configure 메소드오버로딩해서

매개변수로 AuthenticationManagerBuilder 가 주어졌을 때는 해당 객체의 userDetailsService 를 사용하도록 

추가해줍니다.

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(customUserDetailService);
}

 

 

4. OAuth2 User 서비스 생성 

@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {

    MemberRepository memberRepository;
    HttpSession httpSession;

    @Autowired
    public CustomOAuth2UserService(MemberRepository memberRepository, HttpSession httpSession) {
        this.memberRepository = memberRepository;
        this.httpSession = httpSession;
    }

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2UserService delegate = new DefaultOAuth2UserService();
        OAuth2User oAuth2User = delegate.loadUser(userRequest);

        // 서비스 구분을 위한 작업 ( 구글 / 네이버 )
        String registrationId = userRequest.getClientRegistration().getRegistrationId();
        String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();

        String email;
        Map<String, Object> response = oAuth2User.getAttributes();

        // 네이버
        if (registrationId.equals("naver")) {
            Map<String, Object> hash = (Map<String, Object>) response.get("response");
            email = (String) hash.get("email");
        //구글
        } else if (registrationId.equals("google")) {
            email = (String) response.get("email");
        } else {
            throw new OAuth2AuthenticationException("허용되지 않는 인증입니다.");
        }


        MemberDTO memberDTO;
        Optional<MemberDTO> optionalMmeberDTO = memberRepository.findByEmail(email);

        //이미 가입한 사람 => findbyEmail 로 찾은 DTO 가져옴
        if (optionalMmeberDTO.isPresent()) {
            memberDTO = optionalMmeberDTO.get();
        //새로 가입 => 새로 DTO 만들어서 저장
        } else {
            memberDTO = new MemberDTO();
            memberDTO.setEmail(email);
            memberDTO.setRole("USER");  // Enum을 사용하면 Role.ROLE_USER 형식으로 사용, 여기선 String - default 값
            memberRepository.registerMember(memberDTO);
        }

        // 로그인 된 뒤 처리 => 세션 등록
        httpSession.setAttribute("sessiondto", memberDTO);
        return new DefaultOAuth2User(
                Collections.singleton(new SimpleGrantedAuthority(memberDTO.getRole()))
                , oAuth2User.getAttributes()
                , userNameAttributeName
        );
    }
}


5. Controller 맵핑 
// oauth 파라미터 => 리다이렉트로 맵핑 
 @GetMapping("/login/{oauth2}")
    public String loginGoogle(@PathVariable String oauth2) {
        return "redirect:/oauth2/authorization/" + oauth2;
    }


6. View href
<a href="/login/google">Google Login</a>
<a href="/login/naver">Naver Login</a>

 

 

이렇게 설정해두고, Google, Naver 에서 로그인 API 를 사용할 수 있도록 각 사이트에서 

Application 을 생성, 내 URL 을 등록, 리디렉션 설정을 해주면 OAuth2 를 사용한 로그인이 가능해집니다. 

 

[ Google Cloud - OAuth API 등록 ] 
1. 프로젝트 생성 
2. 해당 프로젝트에서 OAuth 동의화면 
- 어플설정하고 저장 
- scope 범위 : 요청할 data, 서비스 범위 
- 사용자 : 외부 => 사용자 유저 추가 

3. 사용자 인증정보 - 만들기 - OAuth 클라이언트 ID 만들기 
- 어플리케이션 유형 : 웹 어플리케이션 
- 승인된 리디렉션 URI : 
http://localhost:8080/login/oauth2/code/google 

(/login/oauth2/code/사이트) 고정

naver 에서는 
http://localhost:8080/login/oauth2/code/naver 

주소로 callback 주소를 적어주면 됩니다. 

- 생성 후 받게되는 클라이언트 ID / PW  를 application-oauth.properties 에 등록해주면 됩니다.

노출되지 않도록 gitignore, 암호화 등을 활용해 꼭! 주의해서 관리해주어야 합니다.

 

( 네이버의 경우도 과정이 크게 다르지 않으니 가이드를 읽으며 따라가시면 될 것 같습니다. )