안녕하세요. 이번 시간에는 passport를 사용해 facebook 아이디로 로그인을 구현해보겠습니다. 이것을 응용하면 google이나 twitter, kakao 등 passport를 지원하는 SNS 아이디로 로그인할 수 있습니다.
우선 passport-facebook을 설치합니다.
npm install --save passport-facebook
설치가 완료되었으면 페이스북에 로그인 요청을 보낼 라우터를 추가합니다.
route.js
... // 이전 시간 코드에서 계속
router.get('/auth/facebook', passport.authenticate('facebook', {
authType: 'rerequest', scope: ['public_profile', 'email']
}));
router.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/' }), function(req, res) {
res.redirect('/');
});
전 시간과 달리 router에 두 개를 추가했습니다. /auth/facebook은 로그인 요청을 할 링크입니다. 이 링크를 html로 만들고 클릭하면 passport를 통해 페이스북으로 로그인 요청이 전송됩니다. authenticate 메소드 뒤의 facebook은 사용할 전략의 이름을 적어주면 됩니다.
authType: 'rerequest'는 매번 로그인 할 때마다 뒤의 public_profile과 email을 달라고 요청하는 겁니다. 이것을 해둬야 실수로 사용자가 요청을 거절했을 때 다음 로그인 시 다시 얻어올 수 있습니다. 뒤에 scope는 페이스북에 사용자에 대한 정보로 무엇을 요청할 지 정하는 부분입니다. 친구목록이나 좋아요한 페이지 등등 다양한 정보를 얻어올 수 있습니다.
/auth/facebook/callback은 페이스북이 검증을 마치고 난 결과를 전송해주는 주소입니다. 여기로 전송한 정보를 처리하는 코드를 만들어보죠. 지난 시간 만들었던 passport.js의 LocalStrategy 아래에 다음 코드를 추가해줍니다.
passport.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const FacebookStrategy = require('passport-facebook').Strategy; // 이 부분 추가
const Users = require('./user');
module.exports = () => {
... // 이전 시간 코드에서 계속
passport.use(new FacebookStrategy({
clientID: '페이스북 클라이언트 아이디',
clientSecret: '페이스북 클라이언트 시크릿',
callbackURL: '홈페이지주소/auth/facebook/callback',
passReqToCallback: true,
}, (req, accessToken, refreshToken, profile, done) => {
User.findOne({ id: profile.id }, (err, user) => {
if (user) {
return done(err, user);
} // 회원 정보가 있으면 로그인
const newUser = new User({ // 없으면 회원 생성
id: profile.id
});
newUser.save((user) => {
return done(null, user); // 새로운 회원 생성 후 로그인
});
});
});
};
슬슬 코드가 콜백 지옥으로 빠져들어가고 있네요. 찬찬히 살펴봅시다. 일단 passport-facebook도 Strategy를 사용합니다. 전략이라고 했죠? 페이스북 로그인은 페이스북 서버에서 clientID, clientSecret, callbackURL을 검사합니다. 이 부분은 나중에 무엇을 넣어야하는지 알려드릴게요.
passReqToCallback 옵션은 지난 시간에 설명드렸습니다. 뒤의 콜백 함수에 req 매개변수를 추가해주죠.
accessToken, refreshToken은 페이스북 API를 사용할 수 있는 토큰을 전달해줍니다. 만약 페이스북이 토큰 내놔라! 라고 하면 이 토큰을 주면 됩니다. profile은 간단한 페이스북 사용자의 정보를 알려줍니다. 별로 알려주는 게 많이 없어서 추가적인 정보를 원한다면 추가 API를 호출해야 합니다.
이제 전략 부분을 설명하겠습니다. 일단 profile.id
로 이미 우리 사이트의 회원인가를 조회해봅니다. 만약 우리 사이트에 이미 가입되어 있으면 done(err, user)
로 바로 로그인합니다. 회원이 아니라면 새로 회원가입하는 거죠.
거의 다 되었는데 이제 clientID와 clientSecret을 넣어야합니다. 이것이 있어야 페이스북에서 보내준 결과가 올바른 사이트에 전달되었는지 확인할 수 있거든요. 이것을 얻으려면 페이스북 개발자 홈페이지에 접속해야 합니다.
로그인 후 상단 오른쪽 내 앱 -> 새 앱 추가 -> 웹사이트를 누르세요. 원하는 앱 이름을 적고 Create New Facebook App ID를 누르면 됩니다.
저는 test로 앱을 만들었는 데 이름은 원하는 걸로 바꾸세요. 정보를 알맞게 적고 앱 ID 만들기를 누릅니다. 사이트 주소도 넣어줍니다.
이제 오른쪽 위 내 앱 -> test에 가면 clientID와 clientSecret을 확인할 수 있습니다.
마지막으로 좌측 메뉴에서 제품 -> 제품 추가를 클릭하여 Facebook 로그인 제품을 활성화합니다. 웹을 클릭한 후 사이트 주소를 입력하면 됩니다. 나머지 것들은 건너뛰어도 됩니다.
좌측 메뉴에 Facebook 로그인이 추가되었는지를 확인합니다.
위의 코드를 활용해서 다른 SNS 로그인도 구현해보세요. 저는 현재 페이스북, 구글+, 트위터, 카카오, 네이버 이렇게 다섯 개를 사용중입니다. 다음 시간에는 socket.io에 대해 알아보겠습니다.
근데 한 가지 궁금한 점이 있는데
제가 연동 해제 기능을 해보려고 해서 passport에서 받아온 token이나 id값을
session에 저장 후 연동 해제 버튼을 클릭 시 서버단에서 해제를 하려고 합니다.
근데 no authentication key 라는 에러 메세지가 나오고 되지 않습니다..
혹시 passport에서 받은 값들이 후에 사용 될 때 유효하지 않는 값이 되어버리는 건가요?