로그인 처리 플로우는 아래와 같다.
인가 코드 받기 -> 토큰 받기 -> 사용자 정보 가져오기
해당 글에서는 인가 코드 받기는 클라이언트 페이지에서, 토큰 받기와 사용자 정보 가져오기는 서버에서 처리할 예정이다.
위 플로우 대로 처리되기 위해 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 문서에서 상세하게 확인할 수 있다.
카카오 개발자센터에서 설정한 값과 코드상 설정한 값이 상이할 경우 아래 화면처럼 에러페이지가 노출된다.
해당 경우는 페이지 안 해결방안을 클릭하면 해당 에러코드에 대한 원인을 상세하게 확인할 수 있다.
값을 올바르게 설정할 경우 카카오 로그인 페이지가 노출된다.
로그인에 성공하면 앞서 설정한 동의 항목이 노출된다.
동의항목 설정을 완료하면 앞서 설정한 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 사이트에서 연결을 해제한 후 다시 테스트를 진행하면 된다.
소스코드
관련글
2022.08.16 - [Web Programming] - 카카오 로그인 쉽게 구현하기 1편 - Kakao Developers 설정
2022.08.17 - [Web Programming] - 카카오 로그인 쉽게 구현하기 2편 - 개발 환경 설정
'Web Programming' 카테고리의 다른 글
네이버 로그인 쉽게 구현하기 3편 - 로그인 구현하기 (SpringBoot + Vue.js) (2) | 2023.01.22 |
---|---|
네이버 로그인 쉽게 구현하기 2편 - 개발 환경 설정 (0) | 2023.01.22 |
네이버 로그인 쉽게 구현하기 1편 - Naver Developers 설정 (0) | 2023.01.22 |
카카오 로그인 쉽게 구현하기 2편 - 개발 환경 설정 (0) | 2022.08.17 |
카카오 로그인 쉽게 구현하기 1편 - Kakao Developers 설정 (1) | 2022.08.16 |