ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • passport를 이용한 GitHub 로그인
    javascript 2020. 3. 15. 17:43

    이번주 과제에서 해본 github로그인을 passport 위주로 간단히 정리해두기.

    passport

    OAuth인증을 간편하게 할 수 있는 Node JS 미들웨어이다.

    * OAuth ? 웹, 앱 서비스에서 제한적인 권한을 요청해 사용할 수 있는 키를 발급해주는 것

     

    다양한 strategy(passport에서 쓰는 인증방식)가 있다.
    ex) GitHub으로 로그인(GitHub strategy), Facebook으로 로그인(facebook strategy)

    passport Document
    passport-github Document

     

    설치하기

    터미널에서 아래 명령어를 입력한다.

    // passport 관련 모듈
    npm install --save passport
    npm install --save passport-github
    
    // 세션 관련 모듈
    npm install --save express-session

    yarn을 이용할 경우 yarn add ~ 를 입력. (ex. yarn add passport)

     

    GitHubStrategy 설정, 응답된 user정보 처리

    GitHub OAuth페이지에서 애플리케이션을 등록 후 받은 clientID, clientSecret값을 보안을 위해 환경변수로 설정하여 입력한다.

    OAuth페이지에 입력한 callback URL(인증 후 받을 request URL)을 입력한다.

    // /config/passport.js
    const passport = require('passport');
    const GitHubStrategy = require('passport-github');
    const User = require('../models/User');
    
    // strategy를 미들웨어로
    passport.use(new GitHubStrategy.Strategy({
        clientID: process.env.GITHUB_CLIENT_ID,
        clientSecret: process.env.GITHUB_CLIENT_SECRET,
        callbackURL: 'http://127.0.0.1:3000/login/github/callback'
      },
      async (accessToken, refreshToken, profile, cb) => {
        try {
          // profile로 들어온 사용자 정보를 활용
          const { name, login: githubID, html_url: githubURL } = profile._json;
          // 연결해둔 mongoDB 내 User에서 검색
          let user = await User.findOne({ githubID });
          // User에 없으면 추가로 저장
          if (!user) {
            user = new User({
              name,
              githubID,
              githubURL
            }).save();
          }
    
          return cb(null, user);
        } catch (err) {
          return cb(err);
        }
      }
    ));
    
    // user를 session에 저장
    passport.serializeUser((user, done) => { done(null, user); });
    // 로그인 성공 후, 페이지 접근 시 수행됨. session에 저장된 값을 이용해 DB에서 사용자 정보를 가져와 Request에 넘겨준다
    passport.deserializeUser((user, done) => { done(null, user); });

    OAuth용 토큰

    accessToken은 페이스북의 Open API를 호출하는 기능을 사용할 수 있다.

    refreshToken은 accessToken이 만료되었을 때, 재발급을 요청할 수 있다.

     

    app.js 에서 passport를 미들웨어로 등록

    favicon, assets(css, js)등 설정 이후에 passport를 미들웨어로 등록한다.
    이전에 작성할 경우, favicon이나 assets 수행 시 불려지는 파일들을 request하는 만큼 deserializeUser()함수를 호출하며 자원을 낭비하게 된다.
    express-session Document

    require('dotenv').config();
    const express = require('express');
    const app = express();
    const session = require('express-session');
    const passport = require('passport');
    
    // favicon설정, assets(css, js...)설정 등
    app.set('view engine', 'pug');
    app.set('views', path.join(__dirname, './views'));
    app.use(express.static(path.join(__dirname, './public')));
    
    // 세션정보 설정
    app.use(session({
      secret: process.env.SECRET_CODE,
      cookie: { maxAge: 60 * 60 * 1000 },
      resave: true,
      saveUninitialized: false
    }));
    
    require('./config/mongoose');
    // strategy 처리
    require('./config/passport');
    // 초기화. user정보가 req.user로 들어가게 됨
    app.use(passport.initialize());
    // passport 내에서 session을 사용해 로그인을 지속시킴
    app.use(passport.session());

     

    Router 설정

    login.html에서 submit버튼 클릭 시, action='/login/github', method='POST' 로 전송한다. (코드 생략)

    passport.authenticate로 github strategy가 호출되어 인증처리를 수행한다.

    // /routes/login.js
    const express = require('express');
    const router = express.Router();
    const passport = require('passport');
    
    router.get('/', (req, res, next) => {
      try {
        res.render('login');
      } catch(err) {
        next(err);
      }
    });
    
    // github 로그인(인증)페이지로 이동
    router.post('/github', passport.authenticate('github'));
    
    // 인증처리 후 github에서 콜백해준 url
    router.get('/github/callback',
      passport.authenticate(
          'github',
          // 실패 시 로그인페이지로 다시 이동
          { failureRedirect: '/login' }),
        // 성공 시 home으로 이동
          (req, res) => {
            res.redirect('/');
          }
    );

     

    로그인 여부 체크

    로그인이 필요한 페이지에 접근 시, isAuthenticated() 미들웨어를 이용해 로그인을 체크한다.
    로그인되어 req.user가 있으면 next()로 다음 작업을 진행하고, 로그인이 안된 경우 login페이지로 리다이렉트시켜 로그인을 유도한다.

    const isAuthenticated = (req, res, next) => {
      if (req.user) {
        next();
      } else {
        res.status(301).redirect('/login');
      }
    };
    
    router.get('/', isAuthenticated, async (req, res, next) => {
      try {
        const problems = await Problem.find().lean();
    
        if (!problems.length) {
          res.render('index', { noProblems: 'There is no quiz registered'});
        }
        res.render('index', { problems });
      } catch(err) {
        next(err);
      }
    });

     

    로그아웃

    app.post('/logout', function(req, res, next) {
      req.session.destroy(() => {
        req.session;
      });
      res.redirect('/login');
    });

     

    댓글

Designed by Tistory.