문의 시, 사용하시는 개발환경과 디벨로퍼스 앱ID를 알려주세요.
개발환경 - Express.js / 디벨로퍼스 앱ID : 909040
express를 이용하여 passport-kakao를 사용하여 구현중에 있습니다.
다음은 passport에 대한 코드입니다.
- passport/index.js
const passport = require("passport");
const Member = require("../models/member");
const kakao = require('./kakaoStrategy');
module.exports = () => {
passport.serializeUser((user, done) => { // 로그인 시 session 저장
done(null, user.kakaoId);
});
// id -> req.session.kakaoId를 의미
passport.deserializeUser((id, done) => { // 로그인 시 세션 불러오기. req.user로 접근 가능!
Member.findOne({ kakaoId: id })
.then(member => done(null, member))
.catch(err => done(err));
});
kakao();
}
- passport/kakaoStrategy.js
const passport = require("passport");
const KakaoStrategy = require('passport-kakao').Strategy;
const Member = require('../models/member')
module.exports = () => {
passport.use(new KakaoStrategy({
clientID: process.env.KAKAO_APIKEY, // 카카오에서 발급해주는 아이디
callbackURL: process.env.REDIRECT_URL, // 카카오 인증 결과 라우터 주소
}, async (accessToken, refreshToken, profile, done) => {
try {
// 기존에 카카오를 통해 회원 가입한 사용자가 있는지 조회
const exUser = await Member.findOne({ kakaoId: profile.id });
if (!exUser) { // 있으면 사용자 정보와 함께 done 함수를 호출하고 종료
// 없으면 회원 가입 진행
// 인증 후 콜백 라우터로 accessToken, refreshToken과 profile을 보냄.
const newUser = await Member.create({
kakaoId: profile.id
});
return done(null, newUser);
}
return done(null, exUser);
} catch (error) {
console.error(error);
done(error);
}
}));
}
카카오 로그인 → 카카오 로그인 화면 → 로그인 성공 시 로그인 콜백 [GET] → res.json의 msg를 전송.
여기까지 진행했을 때는 req.user의 값과 req.session이 저장되는 것을 확인했습니다.
이것은 req.session에 대한 것을 콘솔에 찍었을 때 나타낸 것입니다. passport의 user라는 키 값에 카카오 id가 잘 들어가는 것을 확인했습니다.
아래 코드는 해당 로그인과 로그인 콜백에 대한 코드입니다.
// 로그인 인가 요청
authRouter.get("/login", passport.authenticate("kakao"));
// 로그인 콜백 요청
authRouter.get(
"/login/callback", passport.authenticate('kakao'), (req, res) => {
try {
const user = req.user;
console.log(JSON.stringify(user));
console.log(JSON.stringify(req.session));
if (!user) {
return res.status(400).json({
msg: "사용자가 존재하지 않음."
})
}
if (user.name === null) {
return res.json({ msg: "sign_up"})
// res.redirect('/auth/join')
} else {
return res.json({ msg: "success"})
// res.redirect('/auth/main')
}
} catch (error) {
return res.status(500).json({
message: error.message,
});
}
}
);
이 이후 react 환경의 프론트엔드에서는 msg의 값이 sign_up인 경우 회원 가입 페이지로 navigate하여 회원가입을 진행하게 될 경우 다음과 같은 백엔드 코드가 실행됩니다.
authRouter.post('/join', async (req, res) => {
try {
console.log(JSON.stringify(req.session));
console.log(req.user.kakaoId);
const target = req.user.kakaoId;
// 받은 값으로 회원 가입 완료.
await Member.updateOne({ kakaoId: target }, {
$set: {
name: req.body.name,
studentId: req.body.studentId,
club: req.body.club,
}
});
res.status(200).json({
msg: '회원 가입 성공'
});
} catch (error) {
console.error(error);
res.status(400).json({
message: error.message
});
}
});
이후 이 POST 요청이 실행됐을 때, target의 값이 undefined가 저장되어 에러가 나는 상황입니다.
여기서 각각 req.session과 req.user.kakaoId를 콘솔에 찍어봤을 때 다음과 같이 나왔습니다.
req.user가 왜 undefined인지 문제를 해결해주시면 감사하겠습니다…