카테고리 없음

[TaskApp] KAKAO 로그인 구현 하기

MoveForward 2024. 6. 17. 14:56

구글, 네이버 로그인에 이어 카카오 로그인을 구현하겠다.

 


1. KAKAO OAuth 서비스 등록하기

https://developers.kakao.com

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

1-1) 애플리케이션 추가하기

"애플리케이션 추가하기" 를 클릭한다.

 

애플리케이션 추가하기 > 앱 이름 : "task app project"

> 회사명 : "개인"

> 카테고리 : "라이브러리/데모"

※ '회사명' , '카테고리' 는 임의로 작성하였다.

"저장" 버튼을 클릭하여 애플리케이션을 추가한다.

 

추가된 애플리케이션 "task app project" 를 확인할 수 있다.

"task app project" 를 클릭하여, 애플리케이션의 설정으로 접속한다.

 

 

1-2) 애플리케이션 설정하기

카카오 로그인 > 활성화 설정 > 상태 : "ON"

 

OpenID Connent 활성화 설정 > 상태 : "ON"

Redirect URL : 추가 - "http://localhost:8080/login/oauth2/code/kakao"

 

 

이 부분이 중요하다.

동의항목 > 개인정보 > '닉네임' , '카카오계정(이메일)' - "필수동의"

 

[문제 상황 - 동의항목 (카카오계정(이메일) 추가하기)]

여기서 '닉네임' 은 "사용 안 함" 으로 설정 되어 있고, 이를 "필수 동의" 로 변경할 수 있었지만,

'카카오계정(이메일)' 은 "권한없음" 으로 설정되어 있다.

 

이 것은 "비즈 앱" 으로 설정되어 있지 않기 때문이다.

이전에는 "비즈 앱" 으로 설정 되어 있지 않았어도, 이메일 정보를 사용가능 했지만, 최근 "비즈 앱" 에 한해서 이메일 정보를 사용가능하도록 제한 해 둔 것 같다.

 

따라서 "비즈 앱" 으로 현재 애플리케이션을 등록해야 한다.

위 이미지는 이미 비즈 앱으로 등록된 애플리케이션의 화면이다.

내 애플리케이션> 앱 설정 > 비즈니스 > 비즈 앱 등록 을 통해 비즈 앱으로 등록한다.

※ 비즈 앱 등록은 안내를 쭉 따라가면 되기 때문에, 설명은 생략하겠다.

(비즈 앱 등록을 위해선 애플리케이션 대표 이미지를 등록해야 한다.)


1-3) "Client Secret" , "Client ID" 확인하기

보안 > Client Secret > 코드 

Client Secret 를 확인한다.

앱 키 > 앱 키 > REST API 키

키를 확인한다.


2. application-oauth.yml 에 KAKAO OAuth 정보 등록하기

spring:
  security:
    oauth2:
      client:
        registration:
          
          #GOOGLE 'client-id' , 'client-secret' , 'scope'
          # google 생략
          
          #KAKAO 'client-id' , 'client-secret' , 'scope'
          kakao:
            client-id: "your-kakao-client-id"
            client-secret: "your-kakao-client-secret"
            scope:
              - profile_nickname
              - account_email

            #KAKAO Spring Security 수동 입력
            redirect-uri: http://localhost:8080/login/oauth2/code/kakao
            authorization-grant-type: authorization_code
            client-name: Kakao
            client-authentication-method: client_secret_post


          #NAVER 'client-id' , 'client-secret' , 'scope'
            #NAVER Spring Security 수동 입력
            # naver 생략


        provider:
          #NAVER provider 등록
          # naver provider 생략


          #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: kakao_account

<KAKAO 'client-id' , 'client-secret' , 'scope' 등록>

'client-id' 는 앞서 확인한 'REST_API 키' 이다.

'client-secret' 는 앞서 확인한 'client-secret' 코드 이다.

'scope' 는 동의항목에 있는 항목의 ID 를 입력한다. "profile_nickname" , "account_email"

 

<KAKAO Spring Security 수동 입력>

#KAKAO Spring Security 수동 입력
redirect-uri: http://localhost:8080/login/oauth2/code/kakao
authorization-grant-type: authorization_code
client-name: Kakao
client-authentication-method: client_secret_post

네이버와 모두 동일하지만, 'client-authentication-method: client_secret_post' 가 추가되었다.

스프링 부트의 버전이 2.x.x 에서 3.x.x 로 넘어가면서 추가되었다.

보안을 위해 'client-secret' 를 사용하는데, 이를 적극적으로 명시해주기 위함이다.

 

※ 만약 'client-authentication-method: client_secret_post' 을 추가하지 않으면,

이 오류가 발생하게 된다.

 

<KAKAO provider 등록>

#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: kakao_account

네이버와 마찬가지로 provider 를 등록해야 한다.


3. OAuthAttributes.class

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@ToString
public class OAuthAttributes {
    private Map<String, Object> attributes;
    private String nameAttributeKey;
    private String username;
    private String email;
    private UserRole role;

    //인증자가 누구인지 구분 메서드
    public static OAuthAttributes of(String registrationId,
                                     String usernameAttributeName,
                                     Map<String, Object> attributes) {
        //1. Google
        if (registrationId.equals("google")) {
            return ofGoogle(usernameAttributeName, attributes);
        }

        //2. Kakao
        if (registrationId.equals("kakao")) {
            return ofKakao(usernameAttributeName, attributes);
        }

        //3. Naver
        if (registrationId.equals("naver")) {
            return ofNaver(usernameAttributeName, attributes);
        }

        return null;
    }

    private static OAuthAttributes ofKakao(String usernameAttributeName, Map<String, Object> attributes) {
        Map<String, Object> response = (Map<String, Object>) attributes.get("kakao_account");

        return OAuthAttributes.builder()
                .username((String) response.get("email"))
                .email((String) response.get("email"))
                .attributes(response)
                .nameAttributeKey(usernameAttributeName)
                .build();
    }

    /*ofNaver 메서드 생략*/

    /*ofGoogle 메서드 생략*/
    }
}

"KakaoAccount" 의 속성에 "email" 속성을 가져온다.

 


4. Thymeleaf

<!--login.html 中...-->

<!--간편 로그인-->
<div class="social-login-container">
    <!--구글 로그인-->
    <a href="/oauth2/authorization/google" role="button" class="social-login-btn">
        <img src="/img/google-logo.png" alt="google-login" class="login-img"/>
        구글로 로그인
    </a>
    <!--네이버 로그인-->
    <a href="/oauth2/authorization/naver" role="button" class="social-login-btn" style="background: #1EC800;">
        <img src="/img/naver-logo.png" alt="naver-login" class="login-img"/>
        네이버로 로그인
    </a>
    <!--카카오 로그인-->
    <a href="/oauth2/authorization/kakao" role="button" class="social-login-btn" style="background: #FEE500;">
        <img src="/img/kakao-logo.png" alt="kakao-login"  class="login-img"/>
        카카오로 로그인
    </a>
</div>

"/oauth2/authorization/kakao" 로 URL 을 설정한다.

 


5. 완성 화면

소셜 로그인으로 로그인 된 회원이 DB에 추가된 것을 확인할 수 있다.