Express + passport, 어렵지 않게 사용하기 2

2020. 4. 28. 11:19BACKEND/Node

반응형

# passport - facebook, 소셜로그인 튜토리얼

 

안녕하세요 ❗️

오늘을 passport를 사용해서 로그인 구현을 해볼 예정입니다.

사실 Passport 는 사용해본 적이 없어서 게시글도 쓸겸 만들어봤는데 재밌게 했어요 〰️ 

궁금하지 않으셨나요❓ "소셜로그인 구현은 어떻게 하는 거지?"

passport는 서버의 기본적인 지식이 있어야 구현하는데 어려움없을 거에요.

하지만, 반대로 서버와 express 이 조금 어려운 분들은 passport는 아마 도전이지 않을까 싶네요.

두 편으로 나누어서, 오늘은 소셜 로그인 중, facebook 로그인 구현하는 것을 다뤄볼 예정입니다 🔥

코드는 깃 허브에 올려두었으니 참고하셔도 좋습니다 !

 

*****************  INDEX  *****************

 

🚀 passport 사용 설정 만들기

🎯 passport로 local-login 구현하기

🖍 passport로 social-login 구현하기

 

******************************************** 


🖍 passport로 social-login 구현하기

이번에는 facebook 로그인을 구현해 보겠습니다.

local 로그인을 구현했다면 어렵지 않게 할 수 있을 거에요.

 

1. 페이스북에서 새로운 앱만들기

2. routing

3. 기본 값 설정

 

1.  facebook 개발자 페이지에 들어가서 우리의 앱을 생성해주어야해요❗️ 

'내 앱 > + 앱 만들기' 를 선택해주세요❗️ 

표시 이름을 적어준 후, 앱 ID 만들기를 선택해주세요 〰️ 

그럼 위와 같은 화면이 나올텐데요! '설정 > 기본 설정' 으로 가주세요.

 

바로 이곳❗️ 에 있는 '앱 ID'와 '앱 시크릿 코드'가 필요합니다 〰️ 

앱 시크릿 코드는 '보기'를 눌러서 페이스북 암호를 입력하면 내용이 나오니 그 코드를 복사하셔야 해요❗️ 

이건 잠시후 다시 언급하겠습니다.

 

사용할 플랫폼에 맞추기 위해 플랫폼을 설정해야합니다.

'플랫폼 추가'를 눌러주세요.

 

원하는 플랫폼을 눌러주시면 됩니다 〰️ 이 포스팅에서는 웹사이트를 해볼게요!

 

그럼 위와 같이 사이트의 URL을 입력하라는 창이 나오는데, 자신의 IP 혹은 로컬로 설정해주시면 됩니다 〰️ 

입력하셨다면 우측 하단에 '변경 내용 저장'을 선택해주세요❗️ 

 

 

2. routing

'Express + passport, 어렵지 않게 사용하기 1' 에 이어 코드를 작성해보겠습니다.

이 전 포스팅에서 필수적으로 필요한 부분은 첫 번째 목차 '🚀 passport 사용 설정 만들기' 입니다. 

 

지난 시간에 이어 routes/auth.js 에서 routing을 해주겠습니다. 

 

29줄 ~ 33줄을 추가했습니다. 

이 번에는 callback이라는 것까지 추가 되었네요. 

callback uri는 왜 추가했을까요? 

facebook에서 로그인 요청을 하고 완료되었을 때 다시 돌아와야하기 때문에 필요하게 됩니다.

만약, /auth/facebook에 다시 요청을 보내면 로그인 시도 무한 루프를 돌게되겠죠 🤣

 

authenticate 의 두 번째 인자인 { scope: email } 은 무엇일까요❓ 사용자의 프로필을 받을 때, 기본적으로 제공되는 데이터가 있기도 하고 따로 요청을 해야할 때도 있습니다.

기본 적으로 사용자 식별 아이디, 이름 등은 주지만 email이 필요할 경우에는 이렇게 route 쪽에 scope를 지정해주어야 합니다.

 

그럼 이 정도로 하고 이 번엔 facebook strategy 를 한 번 설정해보겠습니다.

strategy에 대한 설명을 다시 드리자면, 로그인을 하는 로직이 담겨있는 전략법이라는 느낌으로 이해하시면 될 거에요.

 

services/passport.js  내부에 코드를 입력해보겠습니다.

26줄 ~ 40줄을 추가해주었습니다.

사진으로는 조금 헷갈리니 코드만 따로 볼까요❓ 

 

const FacebookStrategy = require('passport-facebook').Strategy;
const passportKey = require('../config/passportKey');
const authService = require('../services/authService');
let passport = require('passport');

//  ...


passport.use(new FacebookStrategy({
        clientID: passportKey.federation.facebook.ID,
        clientSecret: passportKey.federation.facebook.KEY,
        profileFields: ['id', 'displayName', 'email'],
        callbackURL: 'http://localhost:3000/auth/facebook/callback'
    },

    async (accessToken, refreshToken, profile, done) => {
        const socialId = 'facebook:' + profile.id;
        const nickname = profile.displayName;
        const email = profile.emails[0].value;
        const user = await authService.findOrCreate(socialId, nickname, email);
        done(null, user);
    }
));

위와 같은 코드를 추가시켰습니다.

하나씩 살펴보겠습니다.

 

clientID, clientSecret 은 조금 느낌이 오지 않으신가요❓ 

facebook 개발자 페이지에서 발급받았던 ID와 Secret Key입니다.

string 값으로 넣어주면 되는데 저는 따로 .gitignore에 추가해둔 config/ 에 넣어 안전하게 보관했습니다.

 

FacebookStrategy()의 두 번째 인자로 콜백함수가 등록되어져있습니다.

네 가지의 인자를 받으며, 그 중 profile에는 로그인을 성공한 이후, 로그인한 사용자의 프로필을 가져옵니다.

프로필에서는 어떤 값을 얻을 수 있을까요❓

아래 사진 처럼 다양한 데이터를 받을 수 있습니다. 자세한 사항은 공식 문서를 참고해주세요 !

 

데이터를 잘 수집했다면, done 으로 마무리 시켜주면 됩니다. 

profile값에 따라 에러처리를 해주면 더욱 좋겠죠?

 

serializeUser와 deserializeUser은 이미 구현을 해주었기 때문에 따로 다시 설명은 하지 않겠습니다. 

참고하시려면 'Express + passport, 어렵지 않게 사용하기 1' 에서 잠시 언급을 했으니 참고 하시길 바랍니다 !

 

authService.js 를 따로 생성하여 기능을 구현했 주었습니다.

이렇게 보니, passport.js 는 module에 있는 게 조금 더 자연스러울 것 같네요,,,🤣

깃허브에는 아마 modules 내부로 파일 위치가 변경되어 있을 겁니다..!

 

이 번엔 authService.js에 어떻게 구현을 했는지 확인해볼게요.

 

const User = require('../models/user.js');

module.exports = {
    findOrCreate: async (socialId, nickname, email) => {
        try {
            const isThere = await User.userCheck(socialId);
            const user = {
                id: socialId,
                name: nickname,
                email: email,
                state: 0
            }
            if (isThere) {
                console.log('user가 없습니다');
                await User.signup(socialId, nickname, '','', email);
                user.state = 1;
            } else {
                console.log('user가 있습니다');
                user.state = 2;
            }
            return user;
        } catch {
            return false;
        }
    }
}

 

로직이 조금 이해 가시나요?

사용자의 데이터가 이미 있다면, 단순히 user를 반환하고

처음 로그인 한 것이라면 signup이라는 메소드로 데이터를 추가해주었습니다. 

빈 string 값은 password와 salt값이니 그냥 무시해주세요!

 

models/user.js 는 데이터 베이스에 접근하는 코드인데, 자세한 내용은 담지 않겠습니다.

필요하시다면 깃허브 코드를 참고 해주세요!

 

 

이제 한 번 실행을 시켜보도록 하겠습니다 !

웹 브라우저를 통해 테스트를 진행해볼건데요. 저는 chrome을 자주사용해서 chrome으로 접근하겠습니다.

다음과 같이 localhost:3000/auth/facebook을 입력해주세요!

 

이렇게 로그인 페이지로 접근해서 허락을 받습니다. 

개인 정보를 해당하는 앱에 전달해도 되냐는 내용이죠. 

저는 계속을 입력했습니다 !

 

 

 

성공 시 접근되는 localhost/auth 로 정상적으로 접근이 되었네요.

받은 데이터까지 잘 출력이 되었어요!

만약, 통신을 하는 과정에서 Error validating client secret 에러가 뜬 다면 깃 허브 Issue 에 올려두었으니 참고하세요❗️

혹은, deserializeUser가 실행 되지 않아 데이터를 못받을 때가 생길 수도 있는데, 그것도 위의 깃허브 이슈에 담았으니 참고하세요❗️

 

그럼 express + passport, 어렵지 않게 사용하기 시리즈는 여기서 끝내도록 하겠습니다.

반응형