Web Programming

카카오 로그인 쉽게 구현하기 3편 - 로그인 구현하기 (SpringBoot + Vue.js)

놋수저 2022. 8. 17. 19:23
반응형

로그인 처리 플로우는 아래와 같다.

 

인가 코드 받기 -> 토큰 받기 -> 사용자 정보 가져오기

해당 글에서는 인가 코드 받기는 클라이언트 페이지에서, 토큰 받기사용자 정보 가져오기는 서버에서 처리할 예정이다.

위 플로우 대로 처리되기 위해 2개의 클라이언트 페이지와 1개의 API가 필요하다.

1. 클라이언트 페이지

  • 카카오 로그인 버튼 페이지
  • 카카오 로그인 후 Redirect되는 페이지

2. 서버

  • 클라이언트 페이지에서 전달받은 인가코드를 통해 로그인 토큰 발급 및 유저 정보를 조회하는 API

카카오 인증 구현

1. 인가 코드 받기

서비스 서버가 카카오 인증 서버로 인가 코드 받기를 요청한다. 여기서 얻은 인가 코드는 로그인 토큰을 얻기 위해 사용된다.

클라이언트 페이지에서 카카오 로그인창이 노출되고 카카오 계정으로 로그인한 후 앞서 설정한 Redirect URL로 redirect될 때 인가코드를 확인할 수 있다.

 

2. 토큰 받기

앞서 얻은 인가 코드로 로그인 토큰 발급을 요청한다. 토큰 받기를 마쳐야 카카오 로그인을 정상적으로 완료할 수 있다. 해당 토큰으로 로그인이 유효한지 판단할 수 있으며 각 토큰의 역할과 만료 시간에 대한 자세한 정보는 토큰 정보에서 확인할 수 있다. 액세스 토큰의 경우, 토큰 정보 보기로 토큰 유효성을 검사하거나 리프레시 토큰을 사용해 갱신할 수 있다.

 

3. 사용자 정보 가져오기

앞서 얻은 액세스 토큰을 헤더에 담아 사용자 정보를 가져올 수 있다.

 

위 과정 외에도 토큰 갱신, 로그아웃 등의 추가적으로 제공하는 API가 있지만 해당 글에서는 로그인 구현을 위해 필수로 사용해야하는 API만 사용할 예정이다.

인가 코드 받기

카카오 로그인창을 노출시키는 방법은 앞서 카카오 개발자센터에서 발급받은 Key와 Redirect URL 등을 파라미터에 추가하여 호출하면 된다.

    // Login.vue의 일부
    
    doKakaoLogin() {
      const url = 'https://kauth.kakao.com/oauth/authorize?client_id=' +
          process.env.VUE_APP_KAKAO_JS_KEY +
          '&redirect_uri=' +
          process.env.VUE_APP_KAKAO_REDIRECT_URL +
          '&response_type=code&' +
          'scope=account_email birthday gender profile_nickname profile_image'
	  // -- 중략 --
    }

위 함수는 카카오 로그인창을 호출하는 함수이다.

카카오 로그인창을 호출하는 URL은 https://kauth.kakao.com/oauth/authorize 이다.

필수로 추가해야하는 파라미터는 client_id, redirect_uri, response_type, scope 총 4개가 있다.

  • client_id: 카카오 개발자센터에서 발급받은 JavaScript Key
  • redirect_uri: 카카오 개발자센터에서 설정한 Redirect URI
  • response_type: 'code'로 고정
  • scope: 카카오 개발자센터에서 설정한 동의 항목

더 자세한 내용은 카카오 API 문서에서 상세하게 확인할 수 있다.

 

Kakao Developers

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

developers.kakao.com

카카오 개발자센터에서 설정한 값과 코드상 설정한 값이 상이할 경우 아래 화면처럼 에러페이지가 노출된다.

해당 경우는 페이지 안 해결방안을 클릭하면 해당 에러코드에 대한 원인을 상세하게 확인할 수 있다.

 

값을 올바르게 설정할 경우  카카오 로그인 페이지가 노출된다.

 

로그인에 성공하면 앞서 설정한 동의 항목이 노출된다.

동의항목 설정을 완료하면 앞서 설정한 URL로 redirect된다.

로그인 성공 후 Redirect URL은 아래와 같이 설정된다.

http://127.0.0.1:8080/kakao-login?code=tXJkuikMh0lver8NrfQVBQ8Wuq3ctmTjbdIwV8DEJGS2Tx_0OavwJcgRUILsnw1dbD-UDAo9cpcAAAGCr2QNDQ

 

http://127.0.0.1:8080/kakao-login은 카카오 개발자센터에서 설정한 Redirect URL이며 그 뒤에는 code라는 이름의 파라미터가 존재한다. 여기서 code를 이용해 로그인 처리에 필요한 토큰을 얻을 수 있다.

로그인 토큰 얻기

인가 코드는 로그인 토큰을 얻기 위한 코드일 뿐 로그인 처리가 완료된 것이 아니다. 로그인 토큰까지 발급되어야 정상적으로 로그인 처리가 완료된다.

앞서 클라이언트 페이지에서 얻은 인가 코드를 통해 로그인에 필요한 토큰을 얻을 수 있다.

// UserController.java
@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    @PostMapping("/social-login")
    public ResponseEntity<LoginResponse> doSocialLogin(@RequestBody @Valid SocialLoginRequest request) {
        return ResponseEntity.created(URI.create("/social-login"))
                .body(userService.doSocialLogin(request));
    }
}

인가 코드를 통해 로그인 토큰을 가져오는 API 이다. 클라이언트 페이지에서 얻은 인가 코드를 API Body에 전달한다.

@FeignClient(value = "kakaoAuth", url="https://kauth.kakao.com", configuration = {FeignConfiguration.class})
public interface KakaoAuthApi {
    @GetMapping("/oauth/token")
    ResponseEntity<String> getAccessToken(
            @RequestParam("client_id") String clientId,
            @RequestParam("client_secret") String clientSecret,
            @RequestParam("grant_type") String grantType,
            @RequestParam("redirect_uri") String redirectUri,
            @RequestParam("code") String authorizationCode
    );
}

카카오 인증 서버에서 로그인 토큰을 가져온다.

요청 URI은 https://kauth.kakao.com/oauth/token 이다.

로그인 토큰을 가져오기 위해 5개의 파라미터를 설정해야 한다.

  • client_id : 카카오 개발자센터에서 발급 받은 Rest API Key
  • client_secret : 카카오 개발자센터에서 발급 받은 Secret Key
  • grant_type : 클라이언트 페이지에서 얻은 인가 코드를 사용 하기 때문에 "authorization_code"로 고정. 
  • redirect_uri : 카카오 개발자센터에서 설정한 Redirect URI
  • code : 클라이언트 페이지에서 얻은 인가 코드

정상적으로 응답받았을 때의 응답 데이터는 아래와 같다.

{
  "access_token": "9yUOu3_9jM610hz3AduAOxr4xYyBUyouwAL_GLwlCj102gAAAYLDVnKF",
  "token_type": "bearer",
  "refresh_token": "QoyY-O2umtS2pkxXVMBBSCMuHb8BwJi_0EqT5eopCj102gAAAYLDVnKD",
  "expires_in": 21599,
  "scope": "birthday account_email profile_image gender profile_nickname",
  "refresh_token_expires_in": 5183999
}
  • access_token: 사용자 액세스 토큰 값
  • token_type: 토큰 타입, bearer로 고정
  • expires_in: 액세스 토큰의 만료시간 (초)
  • refresh_token: 사용자 리프레시 토큰 값
  • refresh_token_in: 사용자 리프레시 토큰 만료 시간 (초)
  • scope: 인증된 사용자의 정보 조회 권한 범위이다. 범위가 여러 개일 경우, 공백으로 구분한다. 앞서 설정한 동의 항목이 응답된다.

위 과정을 통해 로그인 처리를 완료하였다. 토큰의 만료시간이 정해져 있으므로 필요에 따라 토큰 갱신 API를 이용하면 된다.

여기서 얻은 accss_token으로 앞서 설정한 동의 항목을 바탕으로 로그인한 유저의 정보를 가져올 수 있다.

유저 정보 가져오기

위 과정에서 발급 받은 액세스 토큰으로 유저 정보를 가져올 수 있다.

카카오 서버에서 유저 정보를 가져온 후 필요에 따라 만들고자 하는 서비스에서 회원가입 또는 로그인 처리를 할 수 있다.

유저 정보 조회 API는 헤더에 앞서 발급받은 액세스 토큰을 넣어주어야 한다.

Map<String ,String> headerMap = new HashMap<>();
headerMap.put("authorization", "Bearer " + accessToken);

ResponseEntity<?> response = kakaoUserApi.getUserInfo(headerMap);

액세스 토큰 앞에 "Bearer" + 공백 한 칸(" ")을 더한 값을 헤더에 담아 요청해야 한다.

@FeignClient(value = "kakaoUser", url="https://kapi.kakao.com", configuration = {FeignConfiguration.class})
public interface KakaoUserApi {
    @GetMapping("/v2/user/me")
    ResponseEntity<String> getUserInfo(@RequestHeader Map<String, String> header);
}

요청 URI는 https://kapi.kakao.com/v2/user/me 이다.

정상적으로 응답받았을 때의 응답 데이터는 아래와 같다.

{
  "id": 2396111830,
  "connected_at": "2022-08-20T07:07:28Z",
  "properties": {
    "nickname": "윤성호",
    "profile_image": "http://k.kakaocdn.net/dn/kGHF1/btrIJ79fXS1/A4YrHgVkK78CETTL40LE31/img_640x640.jpg",
    "thumbnail_image": "http://k.kakaocdn.net/dn/kGHF1/btrIJ79fXS1/A4YrHgVkK78CETTL40LE31/img_110x110.jpg"
  },
  "kakao_account": {
    "profile_nickname_needs_agreement": false,
    "profile_image_needs_agreement": false,
    "profile": {
      "nickname": "윤성호",
      "thumbnail_image_url": "http://k.kakaocdn.net/dn/kGHF1/btrIJ79fXS1/A4YrHgVkK78CETTL40LE31/img_110x110.jpg",
      "profile_image_url": "http://k.kakaocdn.net/dn/kGHF1/btrIJ79fXS1/A4YrHgVkK78CETTL40LE31/img_640x640.jpg",
      "is_default_image": false
    },
    "has_email": true,
    "email_needs_agreement": false,
    "is_email_valid": true,
    "is_email_verified": true,
    "email": "dune93@naver.com",
    "has_birthday": true,
    "birthday_needs_agreement": false,
    "birthday": "0731",
    "birthday_type": "SOLAR",
    "has_gender": true,
    "gender_needs_agreement": false,
    "gender": "male"
  }
}

카카오 개발자센터에서 설정한 동의 항목들의 데이터가 응답된다 😄

카카오는 API 문서가 정말 잘 정리 되어있어 구현하기가 정말 쉬웠다.

 

TIP

최초 로그인 이후, 그 다음 부터는 동의 항목 없이 자동으로 넘어간다. 다시 동의 항목 선택을 테스트 하기 위해선

https://accounts.kakao.com/weblogin/account/info 사이트에서 연결을 해제한 후 다시 테스트를 진행하면 된다.

 

소스코드

 

GitHub - vvsungho/social-login-view: 소셜 로그인 클라이언트 화면

소셜 로그인 클라이언트 화면. Contribute to vvsungho/social-login-view development by creating an account on GitHub.

github.com

 

GitHub - vvsungho/social-login-server: 소셜 로그인 서버

소셜 로그인 서버. Contribute to vvsungho/social-login-server development by creating an account on GitHub.

github.com

 

관련글

2022.08.16 - [Web Programming] - 카카오 로그인 쉽게 구현하기 1편 - Kakao Developers 설정

 

카카오 로그인 쉽게 구현하기 1편 - Kakao Developers 설정

카카오 로그인 API  클라이언트 입장에서 수많은 사이트의 모든 아이디 비밀번호를 기억하기는 쉽지 않다. 또한 서비스를 제공해주는 리소스 오너 또한 안전하게 보관하여야 하기 때문에 부담

notspoon.tistory.com

2022.08.17 - [Web Programming] - 카카오 로그인 쉽게 구현하기 2편 - 개발 환경 설정

 

카카오 로그인 쉽게 구현하기 2편 - 개발 환경 설정

개발 환경 설정 카카오 로그인 쉽게 구현하기 1편 - Kakao Developers 설정 카카오 로그인 API  클라이언트 입장에서 수많은 사이트의 모든 아이디 비밀번호를 기억하기는 쉽지 않다. 또한 서비스를

notspoon.tistory.com

 

반응형
LIST