Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions src/routers/kakaoRouter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Router, Request, Response } from "express";
import { KakaoClient } from "../utils/kakao";
import { KakaoTokenData } from "../types/kakao_login/kakaoLoginType";
import handleLogin from "../utils/handleLogin";

const router = Router();

router.get("/url", (req: Request, res: Response) => {
console.log("GET /kakao/url start");
try {
const url = KakaoClient.getAuthCodeUrl();
res.status(200).json({
Expand All @@ -21,16 +19,17 @@ router.get("/url", (req: Request, res: Response) => {
});

router.post("/login", async (req: Request, res: Response) => {
console.log("POST /kakao/login start");
try {
const { code }: { code: string } = req.body;
const kakaoToken: KakaoTokenData = await KakaoClient.getKakaoToken(code);
const userData = await KakaoClient.getUserData(kakaoToken);

console.log("최종적으로 사용할 userData: ", userData);

const dataWithJWT = await handleLogin(userData);
res.status(200).json(dataWithJWT);
const kakaoToken = await KakaoClient.getKakaoToken(code);
if (kakaoToken) {
const userData = await KakaoClient.getUserData(kakaoToken);
if (userData) {
console.log("POST /kakao/login success");
const dataWithJWT = await handleLogin(userData);
res.status(200).json(dataWithJWT);
}
}
} catch (err) {
console.error("POST /kakao/login Error: ", err);
}
Expand Down
13 changes: 13 additions & 0 deletions src/routers/tokenRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const router = Router();
// 이를 위해 token 검증을 수행하는 엔드포인트다.
router.get("/validate", (req: Request, res: Response) => {
if (!req.headers.authorization) {
console.log(
"GET /token/validate 400: authorization 헤더에 jwt가 담겨있지 않습니다"
);
res.status(400).json({
ok: false,
message: "authorization 헤더에 jwt가 담겨있지 않습니다",
Expand All @@ -19,12 +22,14 @@ router.get("/validate", (req: Request, res: Response) => {
}
const accessToken = req.headers.authorization.split(" ")[1];
if (verifyAccessToken(accessToken)) {
console.log("GET /token/validate 200: accessToken이 만료되지 않았습니다");
res.status(200).json({
ok: true,
message: "accessToken이 만료되지 않았습니다",
});
return;
} else {
console.log("GET /token/validate 401: accessToken이 만료되었습니다");
res.status(401).json({
ok: false,
message: "accessToken이 만료되었습니다",
Expand All @@ -48,26 +53,34 @@ router.get("/refresh", async (req: Request, res: Response) => {
if (isVerifyRefreshToken) {
// accessToken은 만료되었지만, refreshToken은 만료되지 않은 경우
const newAccessToken = generateAccessToken(decoded.id);
console.log("GET /token/refresh 200: 새 accessToken을 발급했습니다");
res.status(200).json({
accessToken: newAccessToken,
});
} else {
// 둘 다 만료된 경우
// FE쪽 로그아웃 시켜야 함
console.log(
"GET /token/refresh 401: accessToken, refreshToken 모두 만료되었습니다"
);
res.status(401).json({
ok: false,
message: "Both tokens expired",
});
}
} else {
// accessToken을 디코딩 한 결과가 비어있는 경우
console.log("GET /token/refresh 400: accessToken에 문제가 있습니다");
res.status(400).json({
ok: false,
message: "No Authorized",
});
}
} else {
// refreshToken과 accessToken 모두 존재하지 않는 경우
console.log(
"GET /token/refresh 400: accessToken과 refreshToken이 요청 headers에 존재하지 않습니다"
);
res.status(400).json({
ok: false,
message: "Access token and refresh token not found",
Expand Down
9 changes: 9 additions & 0 deletions src/types/kakao_login/kakaoLoginType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ export type KakaoTokenData = {
refresh_token: string;
};

export type KakaoUserData = {
id: string;
kakao_account: {
profile: {
nickname: string;
};
};
};

export type UserData = {
id: string;
nickname: string;
Expand Down
81 changes: 47 additions & 34 deletions src/utils/kakao.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import axios from "axios";
import axios, { isAxiosError } from "axios";
import dotenv from "dotenv";
import {
KakaoResult,
KakaoTokenData,
UserData,
KakaoUserData,
} from "../types/kakao_login/kakaoLoginType";

dotenv.config();
Expand Down Expand Up @@ -42,44 +42,57 @@ class Kakao {
redirect_uri: this.redirectUri,
};

const data: KakaoResult = await axios
.post("https://kauth.kakao.com/oauth/token", params, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
.then((data) => data.data)
.catch((err) => console.error("getKakaoToken function Error: ", err));

const tokenData: KakaoTokenData = {
access_token: data.access_token,
refresh_token: data.refresh_token,
};
// console.log("kakaoTokenData: ", tokenData);

return tokenData;
try {
const data = await axios.post<KakaoResult>(
"https://kauth.kakao.com/oauth/token",
params,
{
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
}
);
if (data.data) {
const tokenData: KakaoTokenData = {
access_token: data.data.access_token,
refresh_token: data.data.refresh_token,
};
return tokenData;
}
} catch (err) {
if (isAxiosError(err)) {
console.error(
`getKakaoToken func Error: ${err.status}, ${err.response?.data}`
);
}
}
}

/**
* @description 받아온 kakaoToken의 access_token을 사용해 userData를 받아오는 함수
*/
async getUserData(token: KakaoTokenData) {
const data = await axios
.get("https://kapi.kakao.com/v2/user/me", {
headers: {
Authorization: `Bearer ${token.access_token}`,
},
})
.then((data) => data.data)
.catch((err) => console.error("getUserData function Error: ", err));
// console.log("raw user data: ", data);

const userData: UserData = {
id: data.id,
nickname: data.kakao_account.profile.nickname,
};

return userData;
try {
const response = await axios.get<KakaoUserData>(
"https://kapi.kakao.com/v2/user/me",
{
headers: {
Authorization: `Bearer ${token.access_token}`,
},
}
);
const userData = {
id: response.data.id,
nickname: response.data.kakao_account.profile.nickname,
};
return userData;
} catch (err) {
if (isAxiosError(err)) {
console.error(
`getUserData function Error: ${err.status}, ${err.response?.data} `
);
}
}
}
}

Expand Down