-
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 Documentrequire('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'); });
'javascript' 카테고리의 다른 글
Learning JavaScript 후기 1 (0) 2020.02.02 Promise의 프로토타입 then과 catch (0) 2020.01.31 Promise의 생김새와 3가지 상태 (0) 2020.01.31 자바스크립트에서 call, apply, bind (0) 2020.01.31 예측 가능한 콜백, Promise (0) 2020.01.30