반응형
Passport란?
Passport는 이름 그대로 서비스를 사용할 수 있게끔 해주는 여권 같은 역할을 하는 모듈이다.
회원가입과 로그인은 직접 구현할 수도 있지만, 세션과 쿠키 처리 등 복잡한 작업이 많으므로 검증된 모듈을 사용하는 것이 좋다.
그런 방면에서, Passport는 사용하기 좋은 검증된 모듈이다.
특히 facebook이나 kakao, google 같은 소셜 로그인 시에 passport 모듈이 사용된다.
1. Kakao Developers에서 애플리케이션 생성
카카오 디벨로퍼에서 내 애플리케이션 -> 추가하기를 눌러 앱을 생성한다
이렇게 애플리케이션을 생성하면 앱 설정 -> 앱 키에서 REST API 키를 확인할 수 있는데, 추후에 kakao Strategy에 사용될 API KEY이므로 env 파일에 잘 저장해두자!
2. Passport 분석
이제 해당 애플리케이션에 로그인하기 위한 절차를 살펴보자!
1. passport / index.js
먼저, passport 모듈을 사용하기 위한 configuration 코드이다.
const passport = require("passport");
const Member = require("../models/member");
const kakao = require('./kakaoStrategy');
module.exports = () => {
kakao();
passport.serializeUser((user, done) => { // 첫 로그인 시 session 저장
done(null, user.kakaoId);
});
passport.deserializeUser((id, done) => { // 이후 로그인 시 세션 불러오기. req.user로 접근 가능!
Member.findOne({ kakaoId: id })
.then(member => done(null, member))
.catch(err => done(err));
});
}
- serializeUser는 사용자가 로그인할 때 호출된다. 여기서 사용자 객체에서 user.kakaoId 속성을 세션에 저장한다.
- done(null, user.kakaoId): 첫 번째 인자인 null은 에러가 없음을 나타내고, 두 번째 인자인 user.kakaoId는 세션에 저장할 사용자 식별자를 나타낸다.
- deserializeUser는 세션에 직렬화된 사용자가 있는 모든 요청에서 호출된다. 세션에 저장된 kakaoId를 받아 데이터베이스에서 해당 사용자를 찾는다.
- Member.findOne을 통해 일치하는 사용자가 발견되면 done(null, member)가 호출되고, 이 사용자 객체는 req.user로 접근 가능해진다.
- 에러가 발생하거나 일치하는 사용자를 찾지 못한 경우, 에러 객체와 함께 done(err)가 호출된다.
2. passport / kakaoStrategy.js
passport 모듈을 사용하기 위한 전략이다. google, facebook 등 다양한 소셜 로그인이 있지만 여기에선 passport-kakao를 사용하기 때문에 카카오 전략만 살펴볼 예정이다.
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) {
done(error);
}
}));
}
Passport.js의 카카오 OAuth 전략을 설정하여 사용자가 카카오 계정을 통해 로그인할 수 있도록 하는 코드이다.
env 파일에 등록해둔 카카오 APIKEY와 CallbackURL을 사용하여 구현할 수 있다.
이렇게 만들어둔 카카오 전략을 그대로 사용 가능하다.
3. router에 적용
const express = require('express')
const passport = require('passport')
const authRouter = express.Router()
const { logout} = require('../controller/authController')
const Member = require("../models/member");
const {generateToken, verifyToken} = require("../util/auth/jwtHelper");
require('dotenv').config()
// 로그인 인가 요청
authRouter.get("/login", (req, res, next) => {
try {
const token = req.headers.authorization;
req.token = verifyToken(token);
return res.status(200).json({
msg: "success",
token : token
})
} catch(error) {
return next();
}
}, passport.authenticate("kakao"));
// 로그인 콜백 요청
authRouter.get(
"/login/callback", passport.authenticate('kakao'), (req, res, next) => {
try {
const user = req.user;
if (!user) {
return res.status(400).json({
msg: "사용자가 존재하지 않음."
})
}
if (user.name === null) {
// 회원가입으로!
return res.status(200).json({
msg : "sign_up",
kakaoId: user.kakaoId
})
} else {
const token = generateToken(user);
// 메인 화면으로!
return res.status(200).json({
msg: "success",
token : token
})
}
} catch (error) {
next(error);
}
}
);
반응형
'Back-end > Node.js' 카테고리의 다른 글
[2023-2 WINK Project] 2. MongoDB 사용하기 (0) | 2024.05.01 |
---|---|
[2023-2 WINK Project] 1. Express 시작하기 (2) | 2024.04.20 |