안녕하세요. 이번 시간에는 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에 대해 알아보겠습니다.
다음 계정 로그인 기능을 구현하고 로컬이 아닌 실제 윈도우 서버에
서비스를 올리고 주소가 www.abc.com:8001 같은 포트 노출을 막기 위해
URL 재작성 기능을 사용하여 역방향 프록시를 설정하였습니다.
포트 번호를 입력하고 접속해서 카카오 로그인 기능을 사용하면 정상 동작하는데
역방향 프록시 기능을 사용하여 포트 번호 없이 접속하면 404 에러가 발생합니다.
개발자 도구로 내용을 살펴 보니 역방향 프록시로 서비스할 때는 요청 주소가
아래와 같이 잘못 보내지고 있습니다.
포트 번호 사용 시
https://kauth.kakao.com/oauth/authorize?response_type=code&redirect_uri=http%3A%2F%2Fwww.bado.co.kr%3A52273%2Fauth%2Fkakao%2Fcallback&client_id=
포트 번호 없이(역방향 프록시)
http://www.bado.co.kr/oauth/authorize?response_type=code&redirect_uri=http%3A%2F%2F127.0.0.1%3A52273%2Fauth%2Fkakao%2Fcallback&client_id=
혹시 어떤 부분이 문제인지 도움 주실수 있는지요?
확인 부탁드립니다.