카카오, 네이버와 애플까지! 소셜 로그인 구현이 필요했다.
소셜 로그인을 구현하며 고민했던 부분들 위주로 작성해 보겠다.
소셜 로그인 구현
각 redirect uri이 있는데, 이는 소셜 로그인이 성공 후(카카오, 네이버 등에서 로그인 후) 다시 서비스 페이지로 돌아올 페이지 위치이다.
성공 후 발급된 인가코드가 포함되어서 redirect uri로 이동된다!
일반적인 로그인 구현 과정은 다른 블로그 분들이 설명을 너무 잘해주셔서 내가 고민했던 부분들 위주로 작성해 보겠다.
소셜 로그인 성공 후 이전 페이지로 어떻게 보내지?
예를 들어 서비스에서 로그인 전 상태일 경우!
구매하기 클릭 -> 로그인 화면으로 이동 -> 로그인 성공 -> 메인 페이지로 이동이 아니라
구매하기 클릭 -> 로그인 화면으로 이동 -> 로그인 성공 -> 구매하기 페이지로 이동이 자연스럽고
원래의 페이지를 이탈하지 않기 때문에 유저 경험에도 좋다.
returnUrl(로그인 성공 후 다시 돌아올 페이지)를 redirect uri에 어떻게 전달해줘야 할까... 에 대해서 많이 고민했다.
처음에는 카카오에 parameter에 state라는 곳에 값을 넣어서 redirect uri에서 받아서 썼는데
이게 이런 용도가 아닌 거 같은 느낌이...!! 🤔
문서에 따르면 이런 용도라고 한다.
희한하게 각 소셜 로그인 문서에 state가 포함되어 있었고 redirect uri에 포함되어서 전달되었다. (정확히 무엇인지 파악하지 못했다ㅠㅠ)
그래서 내가 생각한 방식은 아래와 같은 과정이다.
- 로그인 페이지로 이동할 때, 돌아갈 페이지를 지정하기 위해
url
이라는 쿼리 스트링을 추가했다.window.location = "/auth/login?url=" + window.location.href;
- 예를들어,로그인 페이지에서
url
은 https://www.test.co.kr/auth/login?url=https://www.test.co.kr/mypage이다.
(여기서, 로그인 성공 후 돌아갈 페이지는 https://www.test.co.kr/mypage이다.) - 로그인 함수에 이
url
쿼리 스트링을 전달하여 이 값이 있다면 localStorage에 저장했다. - redirect uri에서 localStorage에 해당 값이 있다면 모든 과정이 끝난 후 이 경로로 이동시켰다! (값이 없다면 메인 페이지로 이동)
로그인 페이지에서 로그인 버튼 클릭 시 실행되는 함수는 다음과 같다.
goToSocialLogin 함수는 provider(kakao, naver, apple)
과 returnUrl
을 전달받는다.
returnUrl
은 로그인 최종 성공 후 돌아갈 서비스 페이지의 경로로, 이 값이 있다면 localStorage에 저장했다.
function goToSocialLogin(provider, returnUrl) {
const KAKAO_CLIENT_ID = "카카오 client id";
const KAKAO_REDIRECT_URI = `https://${SUBDOMAIN}.test.co.kr/auth/redirect/kakaotalk`;
const NAVER_CLIENT_ID = "네이버 client id";
const NAVER_REDIRECT_URI = `https://${SUBDOMAIN}.test.co.kr/auth/redirect/naver`;
const APPLE_CLIENT_ID = "애플 Bundle IDn";
const APPLE_REDIRECT_URI = `https://${SUBDOMAIN}.test.co.kr/auth/redirect/apple`;
if (returnUrl) {
localStorage.setItem("returnUrl", returnUrl);
}
switch (provider) {
case "kakao":
location.href = `https://kauth.kakao.com/oauth/authorize?client_id=${KAKAO_CLIENT_ID}&redirect_uri=${KAKAO_REDIRECT_URI}&response_type=code`;
break;
case "naver":
location.href = `https://nid.naver.com/oauth2.0/authorize?client_id=${NAVER_CLIENT_ID}&response_type=code&redirect_uri=${NAVER_REDIRECT_URI}`;
break;
case "apple":
location.href = `https://appleid.apple.com/auth/authorize?client_id=${APPLE_CLIENT_ID}&response_type=code%20id_token&redirect_uri=${APPLE_REDIRECT_URI}&scope=name%20email&response_mode=form_post`;
break;
default:
alert("provider값을 확인해주세요:)");
}
}
Redirect uri에서 처리
mount가 되면 localStorage에 returnUrl
의 값이 있는지 확인하고 있다면 그 값을 없으면 "/" 메인으로 저장했다.
로그인 api에서는 전달받은 인가코드를 백앤드에 넘겨주면 된다. 이때, apple의 경우 post형태로 idToken과 신규 회원가입이라면 user에 유저 정보를 전달해 준다. (이미 이전에 연동된 적이 있다면 유저정보를 주지 않기 때문에 user에 값이 안 온다면 연동을 해제하고 다시 시도해 보자)
api를 요청 후 성공 시 location.replace
를 통해 이전에 보고 있던 페이지로 이동시켰다.
페이지 이동 시 location.href
를 사용하면 새로운 페이지로 이동되며, 브라우저의 주소 히스토리에 이동 기록이 남게 된다. 반면에, location.replace
를 사용하면 현재 페이지를 새로운 페이지로 교체해 주소 히스토리가 남지 않는다. 즉, 사용자가 뒤로 가기를 할 경우 redirect uri페이지로 이동하게 되는데 이런 잘못된 페이지 이동을 막기 위해 location.replace
를 사용했다.
const loginRedirectPage = new Vue({
el: '#loginRedirectPage',
data: {
provider : '<?php echo $provider ?>',
returnUrl : '',
},
methods: {
async loginAuth(code){
const loginAuthConfig = {
...
};
try {
const {data: { success, data }} = await axios.request(loginAuthConfig);
if(success) { // 기존 회원으로 로그인 성공
location.replace(this.returnUrl);
} else { // 신규 회원으로 회원가입 페이지로 이동
...
}
} catch (error) {
errorModal(this.returnUrl, error.response.data.message);
}
},
},
mounted() {
const urlParams = new URL(location.href).searchParams;
const code = urlParams.get('code') ? urlParams.get('code') : '';
const idToken = '<?=$_POST['id_token'] ? $_POST['id_token'] : ''?>';
...
if(localStorage.getItem("returnUrl")) { // 로그인 성공 후 되돌아갈 페이지(이전 페이지)
this.returnUrl = localStorage.getItem("returnUrl");
localStorage.removeItem("returnUrl");
} else {
this.returnUrl = '/';
}
this.loginAuth(this.provider === "apple" ? idToken : code);
}
})
애플에서 user가 넘어오지 않는다?!
애플은 최초 로그인 시에만 user정보를 제공하고
그 이후로는 user 정보를 제공하지 않는다고 한다!!!!!!!!!!!!!!!!
이 사실을 모르고 user 정보가 안 와서 반나절을 뭐가 잘못된 건지 찾아다녔다. 🥲
1. https://appleid.apple.com/account/manage로 로그인해 준다.
2. Apple로 로그인에 들어가 연동을 해제할 웹 또는 앱을 선택한다.
3. 로그인 사용을 중단!! 한다.
그럼 정상적으로 idToken과 함께 user 정보를 받을 수 있다.
기존의 프로젝트를 리뉴얼하는 경우 나처럼 이미 연동이 되어있어 user정보가 안 오는 사람들이 많은 거 같았다.
(참고했던 블로그 댓글에 똑같이 했는데 user 정보가 안 온다는 댓글이 정말 많았다 나처럼...ㅎㅎ)
다들 이미 연동이 되어있어 user 정보가 안온게 아닐까 싶다... 🤣
참고자료
'IT > JavaScript' 카테고리의 다른 글
beforeunload로 페이지 이탈 감지하기 (0) | 2024.01.03 |
---|---|
엑셀 다운로드 (0) | 2023.11.01 |
모바일 웹에서 100vh 적용하기 (0) | 2023.11.01 |
모바일 웹에서 app으로 이동(딥링크) (0) | 2023.10.26 |
axios interceptors로 refreshToken을 이용해서 accessToken 재발급 (0) | 2023.10.17 |