Commit ed3d6ae9 authored by Jiwon Yoon's avatar Jiwon Yoon
Browse files

kakaologin

parent b81df368
# 1. 첫 번째 로그인
1. [카카오 로그인] 버튼 클릭 - 'https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code' 으로 접속
2. kakao 쿠키 존재 여부 확인 (첫 로그인에는 존재X)
3. https://accounts.kakao.com/login 접속 및 로그인 인증
4. kakao.com에 종속적으로 쿠키 생성
5. 'https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code'로 돌아와서 동의항목 체크
6. Redirect URI의 주소에 /kakao?code={\*\*\*} code 파라미터에 인가코드 전달됨
7. 인가코드 및 기타 파라미터들을 kauth.kakao.com/oauth/token에 보내고 토큰 받아오기
# 2. 두 번째 로그인부터
1. [카카오 로그인] 버튼 클릭 - 'https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code' 으로 접속
2. kakao 쿠키 존재 여부 확인 (첫 번째 로그인 때 쿠키 생성O)
3. 위 5번부터 동일한 과정 진행
...@@ -21,11 +21,11 @@ export const signup = async (user: SignupUser) => { ...@@ -21,11 +21,11 @@ export const signup = async (user: SignupUser) => {
}; };
export const getKakaoUserData = async (code: string) => { export const getKakaoUserData = async (code: string) => {
const { data } = await axios.post(`${baseUrl}/auth/oauth/kakao`, { const { data } = await axios.post(`${baseUrl}/auth/oauth/kakao/token`, {
code: code, code: code,
}); });
console.log("data=", data); console.log("data=", data);
return data.kakaoUserData; return data;
}; };
export const saveOauthKeys = async ( export const saveOauthKeys = async (
...@@ -42,3 +42,8 @@ export const saveOauthKeys = async ( ...@@ -42,3 +42,8 @@ export const saveOauthKeys = async (
}); });
return data; return data;
}; };
export const getOauthKeys = async (socialType: string) => {
const { data } = await axios.get(`${baseUrl}/auth/oauth/${socialType}`);
return data;
};
...@@ -3,8 +3,8 @@ import { Link, useLocation, useNavigate } from "react-router-dom"; ...@@ -3,8 +3,8 @@ import { Link, useLocation, useNavigate } from "react-router-dom";
import { catchErrors } from "../helpers"; import { catchErrors } from "../helpers";
import { SpinnerIcon } from "../icons"; import { SpinnerIcon } from "../icons";
import { useAuth } from "./auth.context"; import { useAuth } from "./auth.context";
import { REST_API_KEY, REDIRECT_URI } from "../auth"; // import { REST_API_KEY, REDIRECT_URI } from "../auth";
// import { authApi } from "../apis"; import { authApi } from "../apis";
import KakaoLoginImg from "../icons/kakao_login_medium_wide.png"; import KakaoLoginImg from "../icons/kakao_login_medium_wide.png";
interface LocationState { interface LocationState {
...@@ -38,18 +38,17 @@ export const Login = () => { ...@@ -38,18 +38,17 @@ export const Login = () => {
} }
} }
// async function kakaoLogin() { const kakaoLogin = async () => {
// try { // const data = {REST_API_KEY:"", REDIRECT_URI:""}
// // await authApi.kakaoLogin(); try {
// console.log("성공?"); // DB에서 카카오 API키 받아온 후 전달
// } catch (error) { const data = await authApi.getOauthKeys("kakao");
// setLoading(false); console.log(data);
// catchErrors(error, setError); window.location.href = `https://kauth.kakao.com/oauth/authorize?client_id=${data.REST_API_KEY}&redirect_uri=${data.REDIRECT_URI}&response_type=code`;
// } } catch (error) {
// } setLoading(false);
catchErrors(error, setError);
const kakaoLogin = () => { }
window.location.href = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`;
}; };
return ( return (
......
...@@ -2,5 +2,3 @@ export { Login } from "./Login"; ...@@ -2,5 +2,3 @@ export { Login } from "./Login";
export { AuthProvider, useAuth } from "./auth.context"; export { AuthProvider, useAuth } from "./auth.context";
export { SignUp } from "./SignUp"; export { SignUp } from "./SignUp";
export { RequireAuth } from "./RequireAuth"; export { RequireAuth } from "./RequireAuth";
export { REST_API_KEY, REDIRECT_URI} from "./OauthKey"
...@@ -104,34 +104,6 @@ export const createAnswerWithFile = asyncWrap(async (reqExp, res) => { ...@@ -104,34 +104,6 @@ export const createAnswerWithFile = asyncWrap(async (reqExp, res) => {
res.json(newAnswer); res.json(newAnswer);
}); });
// export const getAnswers = asyncWrap(async (reqExp, res) => {
// const req = reqExp as TypedRequest;
// const { surveyId } = req.params;
// try {
// const survey = await surveyDb.getSurveyById(surveyId);
// const answers = await answerDb.getAnswers(surveyId);
// console.log(answers);
// const jsonSurvey = survey?.toJSON();
// if (jsonSurvey && answers) {
// const a = answers.map(async (a) => {
// const targetObj = jsonSurvey.questions.find(
// (q: any) => String(q._id) === String(a._id)
// ) as any;
// if (targetObj) {
// if (a.file.length) {
// targetObj.answers = a.file;
// } else {
// targetObj.answers = a.answers;
// }
// }
// });
// await Promise.all(a);
// }
// return res.json(jsonSurvey);
// } catch (error: any) {
// res.status(422).send(error.message || "설문조사 결과 불러오기 오류");
// }
// });
export const getAnswers = asyncWrap(async (reqExp, res) => { export const getAnswers = asyncWrap(async (reqExp, res) => {
const req = reqExp as TypedRequest; const req = reqExp as TypedRequest;
const { surveyId } = req.params; const { surveyId } = req.params;
......
...@@ -158,26 +158,80 @@ export const signup = asyncWrap(async (req, res) => { ...@@ -158,26 +158,80 @@ export const signup = asyncWrap(async (req, res) => {
}); });
export const kakaoAuthenticate = asyncWrap(async (req, res) => { export const kakaoAuthenticate = asyncWrap(async (req, res) => {
// console.log(req.query); // console.log(req.body);
// const code = req.query.code as string;
console.log(req.body);
const code = req.body.code; const code = req.body.code;
try { try {
const socialKeys = await oauthDb.getSocialKey("kakao");
if (socialKeys) {
const params = new URLSearchParams({ const params = new URLSearchParams({
grant_type: "authorization_code", grant_type: "authorization_code",
client_id: REST_API_KEY, client_id: socialKeys.REST_API_KEY,
redirect_uri: REDIRECT_URI, redirect_uri: socialKeys.REDIRECT_URI,
code: code, code: code,
client_secret: CLIENT_SECRET_KEY, client_secret: socialKeys.CLIENT_SECRET_KEY,
}); });
const kakaoResponse = await axios.post( const kakaoResponse = await axios.post(
"https://kauth.kakao.com/oauth/token", "https://kauth.kakao.com/oauth/token",
params params
); );
console.log(kakaoResponse.data); const kakaoUserData = jwt.decode(kakaoResponse.data.id_token) as any;
console.log("jwt decode:", jwt.decode(kakaoResponse.data.id_token)); //카카오에서 받아온 user data를 db에 저장
// return res.redirect("http://localhost:8080/login/success"); if (kakaoUserData) {
res.json({ kakaoUserData: jwt.decode(kakaoResponse.data.id_token) }); const userExist = await userDb.isUser(kakaoUserData.email);
if (userExist) {
const kakaoUser = await userDb.isSocialType(
kakaoUserData.email,
"kakao"
);
if (kakaoUser) {
// 3) 비밀번호가 맞으면 토큰 생성
const token = jwt.sign({ userId: kakaoUser.id }, jwtCofig.secret, {
expiresIn: jwtCofig.expires,
});
// 4) 토큰을 쿠키에 저장
res.cookie(cookieConfig.name, token, {
maxAge: cookieConfig.maxAge,
path: "/",
httpOnly: envConfig.mode === "production",
secure: envConfig.mode === "production",
});
// 5) 사용자 반환
res.json({
isLoggedIn: true,
email: kakaoUser.email,
});
} else {
return res
.status(422)
.send(
`다른 로그인 방식의 ${kakaoUserData.email} 사용자가 이미 존재합니다`
);
}
} else {
const newUser = await userDb.createUser({
email: kakaoUserData.email,
password: "",
socialType: "kakao",
});
// 3) 비밀번호가 맞으면 토큰 생성
const token = jwt.sign({ userId: newUser.id }, jwtCofig.secret, {
expiresIn: jwtCofig.expires,
});
// 4) 토큰을 쿠키에 저장
res.cookie(cookieConfig.name, token, {
maxAge: cookieConfig.maxAge,
path: "/",
httpOnly: envConfig.mode === "production",
secure: envConfig.mode === "production",
});
// 5) 사용자 반환
res.json({
isLoggedIn: true,
email: newUser.email,
});
}
}
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
res.send("에러"); res.send("에러");
...@@ -192,3 +246,12 @@ export const saveOauthKeys = asyncWrap(async (req, res, next) => { ...@@ -192,3 +246,12 @@ export const saveOauthKeys = asyncWrap(async (req, res, next) => {
return res.json(oauth); return res.json(oauth);
} catch (error) {} } catch (error) {}
}); });
export const getOauthKeys = asyncWrap(async (req, res, next) => {
console.log(req.params);
try {
const socialKeys = await oauthDb.getSocialKey(req.params.socialType);
console.log(socialKeys);
return res.json(socialKeys);
} catch (error) {}
});
...@@ -10,3 +10,8 @@ export const createSocialKey = async (socialKeys: IOauth) => { ...@@ -10,3 +10,8 @@ export const createSocialKey = async (socialKeys: IOauth) => {
const oauth = await newOauth.save(); const oauth = await newOauth.save();
return oauth; return oauth;
}; };
export const getSocialKey = async (socialType: string) => {
const socialKeys = await Oauth.findOne({ socialType: socialType });
return socialKeys;
};
...@@ -16,6 +16,7 @@ export const createUser = async (user: IUser) => { ...@@ -16,6 +16,7 @@ export const createUser = async (user: IUser) => {
password: hash, password: hash,
role: userRole, role: userRole,
avatar: user.avatar, avatar: user.avatar,
socialType: user.socialType,
isNew: true, isNew: true,
}); });
const retUser = await newUser.save(); const retUser = await newUser.save();
...@@ -70,3 +71,8 @@ export const isValidUserId = async (userId: string) => { ...@@ -70,3 +71,8 @@ export const isValidUserId = async (userId: string) => {
return false; return false;
} }
}; };
export const isSocialType = async (socialType: string, email: string) => {
const user = await User.findOne({ email, socialType });
return user;
};
...@@ -6,6 +6,7 @@ export interface IUser { ...@@ -6,6 +6,7 @@ export interface IUser {
password: string; password: string;
role?: Types.ObjectId; role?: Types.ObjectId;
avatar?: Types.ObjectId; avatar?: Types.ObjectId;
socialType?: string;
} }
const validateEmail = (email: string) => { const validateEmail = (email: string) => {
...@@ -25,6 +26,7 @@ const schema = new Schema<IUser>( ...@@ -25,6 +26,7 @@ const schema = new Schema<IUser>(
password: { type: String, select: false }, password: { type: String, select: false },
role: { type: Schema.Types.ObjectId, ref: "Role" }, role: { type: Schema.Types.ObjectId, ref: "Role" },
avatar: { type: Schema.Types.ObjectId, ref: "FileInfo" }, avatar: { type: Schema.Types.ObjectId, ref: "FileInfo" },
socialType: { type: String },
}, },
{ {
toJSON: { toJSON: {
......
...@@ -9,6 +9,10 @@ router.route("/logout").get(authCtrl.logout); ...@@ -9,6 +9,10 @@ router.route("/logout").get(authCtrl.logout);
router.route("/oauth").post(authCtrl.saveOauthKeys); router.route("/oauth").post(authCtrl.saveOauthKeys);
router.route("/oauth/kakao").post(authCtrl.kakaoAuthenticate); router.route("/oauth/kakao/token").post(authCtrl.kakaoAuthenticate);
router.route("/oauth/:socialType").get(authCtrl.getOauthKeys);
// router.param("socialType", authCtrl.getOauthKeys);
export default router; export default router;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment