진행하고 있는 프로젝트에 접근성이 중요해서 카카오톡으로 로그인할 수 있도록 구현했었는데,
내가 짠 구조가 맞는지 의문이 들어 찾아보다가
위 글을 보게 되어 구조를 수정하였다.
수정 전의 카카오 로그인 흐름은 아래와 같았다.
근데
가이드를 다시 읽어보다가
위 다이어그램을 발견했고,
우선 위와 같이 흐름을 수정하였다.
Func loginWithKakao
async loginWithKakao({ code }: LoginWithKakaoInput): Promise<LoginOutput> {
try {
// get access token
const formData = {
grant_type: 'authorization_code',
client_id: process.env.KAKAO_REST_API_KEY,
redirect_uri: process.env.REDIRECT_URI_LOGIN,
code,
client_secret: process.env.KAKAO_CLIENT_SECRET,
};
const {
data: { access_token },
} = await axios
.post(`https://kauth.kakao.com/oauth/token?${qs.stringify(formData)}`)
.then((res) => {
return res;
});
// get user info
const { data: userInfo } = await axios
.get('https://kapi.kakao.com/v2/user/me', {
headers: {
Authorization: 'Bearer ' + access_token,
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
},
})
.then((res) => {
return res;
});
const name = userInfo.properties.nickname;
const profileImg = userInfo.properties.profile_image;
const email = userInfo.kakao_account.email;
const gender = userInfo.kakao_account.gender;
const birth = userInfo.kakao_account.birthday;
const password = // 비밀번호 생성
let intGender = gender === 'male' ? 0 : 1;
// check user exist with email
const { ok: user } = await this.findByEmail({ email });
// control user
let createAccountResult;
if (!user) {
const { ok } = await this.createAccount({
name,
email,
gender: +intGender,
password,
profileImg,
birth,
});
createAccountResult = ok;
}
if (user || createAccountResult) {
return await this.login({ email, password });
} else {
return { ok: false, error: "Couldn't create account in try" };
}
} catch (e) {
console.log(e);
return { ok: false, error: 'Please Refresh and Try One more time' };
}
}
backend에서 동작하는 login with kakao 함수이다.
// get access token
const formData = {
grant_type: 'authorization_code',
client_id: process.env.KAKAO_REST_API_KEY,
redirect_uri: process.env.REDIRECT_URI_LOGIN,
code,
client_secret: process.env.KAKAO_CLIENT_SECRET,
};
const {
data: { access_token },
} = await axios
.post(`https://kauth.kakao.com/oauth/token?${qs.stringify(formData)}`)
.then((res) => {
return res;
});
frontend에서 넘겨준 코드를 통해 access token을 발급받은 후,
// get user info
const { data: userInfo } = await axios
.get('https://kapi.kakao.com/v2/user/me', {
headers: {
Authorization: 'Bearer ' + access_token,
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
},
})
.then((res) => {
return res;
});
access token을 통해 유저 정보를 가져온다.
// check user exist with email
const { ok: user } = await this.findByEmail({ email });
// control user
let createAccountResult;
if (!user) {
const { ok } = await this.createAccount({
name,
email,
gender: +intGender,
password,
profileImg,
birth,
});
createAccountResult = ok;
}
if (user || createAccountResult) {
return await this.login({ email, password });
} else {
return { ok: false, error: "Couldn't create account in try" };
}
그 후 이메일로 유저를 확인하여
이미 계정이 있다면 로그인을, 없다면 유저 정보로 계정을 생성한 후 로그인한다.
이렇게 흐름은 변경하였지만 코드가 섹시하지 못한 것 같아 더 수정해보도록 할 것이다.
또한 현재 token 하나만 반환하고 있는데, 만료 기한을 설정하고 refresh token을 적용하도록 할 것이다.
참고자료
https://velog.io/@max9106/OAuth
'개발 일지' 카테고리의 다른 글
하나의 EC2 안에 테스트 서버까지 구축하기 feat. AWS (2) | 2022.11.19 |
---|---|
Refresh Token - JWT (0) | 2022.04.04 |
KakaoLink API(카카오로 링크 공유하기) in React (0) | 2022.03.29 |
Netlify로 프론트엔드 배포하기 (0) | 2022.03.17 |
Heroku로 백엔드 배포하기 (0) | 2022.03.17 |