패스포트로 사용자 인증하기 9장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03

Slides:



Advertisements
Similar presentations
일정 관리 다이어리 제작 JSP Programming with a Workbook. 학습 목표  사용자의 일정을 관리할 수 있는 다이어리에 대하여 알아보자. JSP Programming with a Workbook2.
Advertisements

2008 년 11 월 20 일 실습.  실험제목 ◦ 데이터베이스 커넥션 풀  목표 ◦ 데이터베이스 커넥션 풀의 사용.

MEAN Stack Front to Back (MEANAuthApp)
Database Laboratory, Hong Ik University
4강. Servlet 맛보기 Servlet 문서 작성 하기 web.xml에 서블릿 맵핑 어노테이션을 이용한 서블릿 맵핑
5강. Servlet 본격적으로 살펴보기-I 프로젝트 만들기 doGet() doPost()
채팅 서버 만들기 10장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
모바일 서버 만들기 13장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
위치기반서비스 서버 만들기 12장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
데이터베이스 사용하기 6장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
9. Deploying mean applications
MEAN Stack Front to Back (MEANAuthApp)
5장 Mysql 데이터베이스 한빛미디어(주).
forms 객체 입력상자 체크상자, 라디오 버튼 목록상자
4장. 웹로직 서버상에서의 JDBC와 JTA의 운용
게시판 만들기 14장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
JSON-RPC 서버 만들기 11장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
4-1장. MySQL 제13장.
3.2 SQL Server 설치 및 수행(계속) 시스템 데이터베이스 master
1. C++ 시작하기.
FTP 프로그램 채계화 박재은 박수민.
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
                              데이터베이스 프로그래밍 (소프트웨어 개발 트랙)                               퍼스널 오라클 9i 인스톨.
MEAN Stack Front to Back (MEANAuthApp)
WinCE Device Driver 실습 #3
학습목표 학습목차 다른 홈페이지의 HTML 파일 코드를 보는 방법에 대해 알아봅니다.
KHS JDBC Programming 4 KHS
뷰 템플릿 적용하기 8장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
- 전자 문서파일 불러오기 방법
5장 Mysql 데이터베이스 한빛미디어(주).
Git 사용법 GitHub 가입 GitHub 새 저장소 만들기 Git 설치 로컬 저장소 만들기 로컬 저장소와 원격 저장소 연결
웹 어플리케이션 보안 2016년 2학기 3. Mongo db.
노드의 기본 기능 알아보기 4장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
인터넷응용프로그래밍 JavaScript(Intro).
Mobile SHI 사용자 메뉴얼 중공업조선CI그룹 전진형( )
UpToDate® Anywhere(UTDA)
2015학년도 PHP 기말 레포트 로그인 홈페이지 제작.
영상처리 실습 인공지능연구실.
Go Lang 리뷰 이동은.
HTTP 프로토콜의 요청과 응답 동작을 이해한다. 서블릿 및 JSP 를 알아보고 역할을 이해한다.
툴 설치 가이드 PrimeTime SynopsysMentor.
Adobe 제품 다운로드 및 설치 방법 안내 Adobe Creative Cloud Adobe License 권한을 받으신 분
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
Nessus 4 설치 정보보호응용 조용준.
노드 간단하게 살펴보기 2장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
MEAN Stack Front to Back (MEANAuthApp)
기말 프로젝트 계획 MVC 패턴 기반 웹 애플리케이션 개발 프로젝트명 : 팀명 : 팀원 :
15강. 폼 데이터 값 검증 Validator를 이용한 검증 ValidationUtils 클래스
14강. 세션 세션이란? 세션 문법 Lecturer Kim Myoung-Ho Nickname 블스
CHAP 21. 전화, SMS, 주소록.
MEAN Stack Front to Back (MEANAuthApp)
STS 에서 웹 서버 설치 방법.
12강. 컨트롤러 컨트롤러 클래스 제작 요청 처리 메소드 제작 뷰에 데이터 전달
암호학 응용 Applied cryptography
13주 실습강의 학기, 소프트웨어 설계 및 실험(Ⅰ).
JSP Programming with a Workbook
세션에 대해 알아보고 HttpSession 에 대해 이해한다 세션 관리에 사용되는 요소들을 살펴본다
시스템 인터페이스 Lab1 X-window 및 명령어 사용.
1. 포털 시스템 사이트 접속 ◎ 포털시스템 ( ) 사이트에 들어갑니다.
Android -Data Base 윤수진 GyeongSang Univ. IT 1.
웹어플리케이션보안 난수화 토큰인증 중부대학교 정보보호학과 이병천 교수.
UpToDate® Anywhere(UTDA)
접근제어 솔루션 계정등록 및 클라이언트 설치.
Homework #3 - 페이지 모듈화 및 로그인처리 -
구글 계정 생성가이드.
이 프레젠테이션은 PowerPoint의 새로운 기능에 대해 안내하며, 슬라이드 쇼에서 가장 잘 보입니다
K PaaS-TA 앱 운영.
MEAN Stack Front to Back (MEANAuthApp)
Presentation transcript:

패스포트로 사용자 인증하기 9장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03 ○ 본 강의 자료는 이지스퍼블리싱에서 제공하는 강의 교안입니다. ○ 본 강의 교안은 아래 출판 서적의 내용을 기준으로 구성되었습니다. 또한 다수의 기타 서적이나 사이트를 참조하였습니다. 레퍼런스를 참조하십시오. 2017, 정재곤, “Do it! Node.js 프로그래밍 (개정판)”, 이지스퍼블리싱 - 강의 교안에 사용된 화면 캡처나 실습 자료의 경우에는 문서 업데이트에 따라 변경될 수 있습니다.

어떻게 하면 사용자 인증을 간단하게 할 수 있을까? 강의 주제 및 목차 강의 주제 어떻게 하면 사용자 인증을 간단하게 할 수 있을까? 목 차 1 패스포트로 로그인하기 2 패스포트 관련 코드를 모듈화하기 3 페이스북으로 로그인하기

1. 패스포트로 로그인하기 난이도 소요시간 30분

패스포트란? 노드에서 사용할 수 있는 사용자 인증 모듈 인증 방식은 Strategy로 만들어져 있음

패스포트의 기본 사용방법 자주 사용되는 코드 형태 local 은 스트래티지의 이름 router.route('/login').post(passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' } )); route.route('/login').post(passport.authenticate('local'), function(req, res) { // 인증 성공시 호출됨., 'req.user'는 인증된 사용자에 대한 정보임 res.redirect('/users/' + req.user.username); } );

authenticate 호출 결과에 따른 처리

플래시 메시지 사용하기 connect-flash 모듈 사용

플래시 메시지 사용하기 오류 메시지를 플래시 메시지로 전달하기 router.route('/login').post(passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login', failureFlash: true } ));

커스텀 콜백 사용하기 라우팅 함수를 등록하고 그 안에서 인증 진행하는 방식 router.route('/login').get(function(req, res, next) { passport.authenticate('local', function(err, user, info) { if (err) { return next(err); } if (!user) { return res.redirect('/login'); } // 패스포트 인증 결과에 따라 로그인 진행 req.login(user, function(err) { return res.redirect('/users/' + user.username); }); })(req, res, next);

스트래티지 설정하기 인증 방식을 결정하는 것이 스트래티지 var passport = require('passport') , LocalStrategy = require('passport-local').Strategy; passport.use(new LocalStrategy( function(username, password, done) { UserModel.findOne({ username: username }, function (err, user) { if (err) { return done(err); } if (!user) { return done(null, false, { message: 'Incorrect username.' }); } if (!user.validPassword(password)) { return done(null, false, { message: 'Incorrect password.' }); return done(null, user); }); ));

스트래티지 설정과 authenticate의 관계

검증 콜백의 사용 인증 정보를 가지고 사용자를 찾아내는 역할 로컬 인증 방식에서 검증 콜백의 사용 방식 스트래티지 안에서 Done() 메소드가 어떻게 호출되는가에 따라 authenticate 의 인증 결과가 달라짐

2. 로컬 인증하기 난이도 소요시간 20분

로컬 인증 사용하기 passport, passport-local, connect-flash 모듈 사용 % npm install passport --save % npm install passport-local --save % npm install connect-flash --save var passport = require('passport'); var flash = require('connect-flash'); … app.use(passport.initialize()); app.use(passport.session()); app.use(flash());

데이터베이스 스키마 수정 이메일 인증이 가능하도록 데이터베이스 스키마 수정 var UserSchema = mongoose.Schema({ email : {type : String, 'default' : ''} , hashed_password : {type : String, required : true, 'default' : ''} , name : {type : String, index : 'hashed', 'default' : ''} , salt : {type : String, required : true} , created_at : {type : Date, index : {unique : false}, 'default' : Date.now} , updated_at : {type : Date, index : {unique : false}, 'default' : Date.now} });

속성의 유효성 검증 email 속성과 hashed_password 속성에 값이 없는지 확인 // 입력된 칼럼 값이 있는지 확인 UserSchema.path('email').validate(function(email) { return email.length; }, 'email 칼럼의 값이 없습니다.'); UserSchema.path('hashed_password').validate(function(hashed_password) { return hashed_password.length; }, 'hashed_password 칼럼의 값이 없습니다.');

모델 객체에서 사용할 수 있는 메소드 정의 static() 메소드를 이용해 모델 객체에서 사용할 수 있는 메소드 정의 // 모델 객체에서 사용할 수 있는 메소드 정의 UserSchema.static('findByEmail', function(email, callback) { return this.find({email : email}, callback); }); UserSchema.static('findAll', function(callback) { return this.find({ }, callback);

설정에서 스키마 등록 부분 수정 config.js 파일을 열고 스키마 등록 부분 수정 module.exports = { server_port : 3000, db_url : 'mongodb://localhost:27017/local', db_schemas : [ {file : './user_schema', collection : 'users5', schemaName : 'UserSchema', modelName : 'UserModel'} ], route_info : [ ] }

로컬 패스포트 인증을 처리할 함수 등록 local-login 이름으로 LocalStrategy 객체 등록 var LocalStrategy = require('passport-local').Strategy; // 패스포트 로그인 설정 passport.use('local-login', new LocalStrategy({ usernameField : 'email', passwordField : 'password', passReqToCallback : true }, function(req, email, password, done) { console.log('passport의 local-login 호출됨 : ' + email + ', ' + password); var database = app.get('database'); database.UserModel.findOne({'email' : email}, function(err, user) { if(err) {return done(err);} // 등록된 사용자가 없는 경우 if(!user) { console.log('계정이 일치하지 않음.'); return done(null, false, req.flash('loginMessage', '등록된 계정이 없습니다.')); }

로컬 패스포트 인증을 처리할 함수 등록 local-login 이름으로 LocalStrategy 객체 등록 // 비밀번호를 비교하여 맞지 않는 경우 var authenticated = user.authenticate(password, user._doc.salt, user._doc.hashed_password); if (!authenticated) { console.log('비밀번호 일치하지 않음.'); return done(null, false, req.flash('loginMessage', '비밀번호가 일치하지 않습니다.')); } // 정상인 경우 console.log('계정과 비밀번호가 일치함.'); return done(null, user); }); }));

클라이언트의 요청 파라미터 매핑 username과 password라는 이름 대신 다른 이름으로 지정 가능

회원가입 기능을 처리할 함수 등록 local-signup 이름으로 LocalStrategy 객체 등록 // 패스포트 회원가입 설정 passport.use('local-signup', new LocalStrategy({ usernameField : 'email', passwordField : 'password', passReqToCallback : true }, function(req, email, password, done) { var paramName = req.param('name'); console.log('passport의 local-signup 호출됨 : ' + email + ', ' + password + ', ' + paramName); // User.findOne이 blocking되므로 async 방식으로 변경할 수도 있음 process.nextTick(function() { var database = app.get('database'); database.UserModel.findOne({'email' : email}, function(err, user) { // 오류가 발생하면 if(err) { return done(err); }

회원가입 기능을 처리할 함수 등록 local-signup 이름으로 LocalStrategy 객체 등록 // 기존에 이메일이 있다면 if(user) { console.log('기존에 계정이 있음.'); return done(null, false, req.flash('signupMessage', '계정이 이미 있습니다.')); } else { // 모델 인스턴스 객체 만들어 저장 var user = new database.UserModel({'email' : email, 'password' : password, 'name' : paramName}); user.save(function(err) { if(err) {throw err;} console.log("사용자 데이터 추가함."); return done(null, user); }); }

패스포트를 위한 메소드 추가 serializeUser() 메소드는 사용자 인증이 성공적으로 진행되었을 때 호출되는 함수 등록 deserializeUser() 메소드는 인증 이후 사용자 요청이 들어올 때마다 호출되는 함수 등록 // 사용자 인증에 성공했을 때 호출 passport.serializeUser(function(user, done) { console.log('serializeUser() 호출됨.'); console.dir(user); done(null, user); }); // 사용자 인증 이후 사용자 요청이 있을 때마다 호출 passport.deserializeUser(function(user, done) { console.log('deserializeUser() 호출됨.');

메소드가 호출되는 방식 상황에 맞게 serializeUser()와 deserializeUser() 메소드가 호출됨

로그인과 회원가입을 위한 라우팅 함수 등록 사용자 로그인과 회원가입 처리 과정

사용자 요청 패스 추가 login, signup, profile, logout 기능을 요청 패스로 추가 요청 패스 요청 방식 설명 / get 홈 화면 조회 /login 로그인 화면 조회 post 패스포트로 사용자 인증을 처리하는 함수 호출 /signup 회원가입 화면 조회 패스포트로 회원 가입을 처리하는 함수 호출 /profile 사용자 프로필 화면 조회 /logout 로그아웃을 처리하는 함수 호출

로그인 요청 처리 login 요청에 대해 passport 객체의 authenticate() 메소드 호출하도록 등록 authenticate() 메소드에서는 ‘local-login’으로 등록된 함수 사용 router.route('/login').post(passport.authenticate('local-login', { successRedirect : '/profile', failureRedirect : '/login', failureFlash : true })); … router.route('/signup').post(passport.authenticate('local-signup', { failureRedirect : '/signup',

프로필 링크 isLoggedIn() 메소드를 호출하여 로그인 여부를 먼저 확인 router.route('/profile').post(function(req, res) { console.log('/profile 패스 요청됨.'); if (req.isAuthenticated()) { console.dir(req.user); if(Array.isArray(req.user)) { res.render('profile.ejs', {user : req.user[0]._doc}); } else { res.render('profile.ejs', {user : req.user}); } } else (req.isAuthenticated()) { res.redirect('/'); });

로그아웃 로그아웃 시에는 req 객체의 logout() 메소드 호출 // 로그아웃 router.route('/logout‘).get(function(req, res) { console.log('/logout 패스 요청됨.'); req.logout(); res.redirect('/'); });

부트스트랩으로 뷰 템플릿 만들기 부트스트랩 사용하여 웹페이지 작성 (http://getbootstrap.com) 네 개의 뷰 템플릿 작성 템플릿 이름 설명 index.ejs 홈 화면을 위한 뷰 템플릿 login.ejs 로그인 화면을 위한 뷰 템플릿 signup.ejs 회원가입 화면을 위한 뷰 템플릿 profile.ejs 사용자 프로필 화면을 위한 뷰 템플릿

index.ejs 템플릿 파일 첫 화면을 위한 템플릿 파일 <div class = "container"> <div class = "jumbotron text-center"> <h1><span class = "fa fa-shopping-cart"></span> 쇼핑몰 홈</h1> <br> <p>로그인하세요.<p> <p>계정이 없으시면 회원가입하세요.</p> <a href = "/login" class = "btn btn-default"> <span class = "fa fa-user"></span>로그인 </a> <a href = "/signup" class = "btn btn-default"> <span class = "fa fa-user"></span>회원가입 </div>

login.ejs 템플릿 파일 로그인을 위한 템플릿 파일 <div class = "container"> <div class = "col-sm-6 col-sm-offset-3"> <h1><span class = "fa fa-sign-in"></span> 로그인</h1> <!-- 인증 처리 후 메시지가 있으면 메시지 표시 --> <% if(message.length > 0) { %> <div class = "alert alert-danger"><% = message %></div> <% } %> <form action = "/login" method = "post" > <div class = "form-group"> <label>이메일</label> <input type = "text" class = "form-control" name = "email"> </div>

login.ejs 템플릿 파일 로그인을 위한 템플릿 파일 <div class = "form-group"> <label>비밀번호</label> <input type = "password" class = "form-control" name = "password"> </div> <button type = "submit" class = "btn btn-warning btn-lg">로그인</button> </form> <hr> <p>계정이 없으세요? <a href = "/signup">회원가입하기</a></p> <p><a href = "/">홈으로</a>.</p>

signup.ejs 템플릿 파일 회원가입을 위한 템플릿 파일 <div class = "container"> <div class = "col-sm-6 col-sm-offset-3"> <h1><span class = "fa fa-sign-in"></span> 회원가입</h1> <!-- 인증 처리 후 메시지가 있으면 메시지 표시 --> <% if(message.length > 0) { %> <div class = "alert alert-danger"><% = message %></div> <% } %> <form action = "/signup" method = "post" > <div class = "form-group"> <label>이메일</label> <input type = "text" class = "form-control" name = "email"> </div>

profile.ejs 템플릿 파일 프로필 표시를 위한 템플릿 파일 <div class = "container"> <div class = "page-header text-center"> <h1><span class = "fa fa-anchor"></span> 사용자 프로필</h1> <a href = "/logout" class = "btn btn-default btn-sm">로그아웃</a> </div> <br> <div class = "row"> <div class = "col-sm-6"> <div class = "well"> <h3><span class = "fa fa-user"></span> 로컬 프로필 정보</h3> <p> <strong>이름</strong> : <% = user.name %><br><br> <strong>이메일</strong> : <% = user.email %> </p>

웹브라우저에서 확인 홈 화면, 회원가입 화면, 로그인 화면, 프로필 화면 ▶ http : //localhost : 3000/

3. 패스포트 관련 코드를 모듈화하기 난이도 소요시간 20분

패스포트 관련 코드를 모듈화하는 과정 PassportExample 프로젝트를 복사하여 PassportExample2 프로젝트로 만듬 패스포트 설정 파일을 별도로 만들어 관리

패스포트 설정 파일 생성 config 폴더 안에 passport.js 파일 만들기 var local_login = require('./passport/local_login'); var local_signup = require('./passport/local_signup'); module.exports = function (app, passport) { console.log('config/passport 호출됨.'); // 사용자 인증에 성공했을 때 호출 passport.serializeUser(function(user, done) { console.log('serializeUser() 호출됨.'); console.dir(user); done(null, user); }); // 사용자 인증 이후 사용자 요청이 있을 때마다 호출 passport.deserializeUser(function(user, done) { console.log('deserializeUser() 호출됨.'); passport.use('local-login', local_login); passport.use('local-signup', local_signup); };

로컬 로그인 Strategy 파일 분리 passport 폴더 안에 local_login.js 파일 만들고 로컬 로그인을 위한 Strategy 파일 분리 var LocalStrategy = require('passport-local').Strategy; module.exports = new LocalStrategy({ usernameField : 'email', passwordField : 'password', passReqToCallback : true }, function(req, email, password, done) { console.log('passport의 local-login 호출됨 : ' + email + ', ' + password); …….

로컬 회원가입 Strategy 파일 분리 passport 폴더 안에 local_signup.js 파일 만들고 로컬 회원가입을 위한 Strategy 파일 분리 ar LocalStrategy = require('passport-local').Strategy; module.exports = new LocalStrategy({ usernameField : 'email', passwordField : 'password', passReqToCallback : true }, function(req, email, password, done) { var paramName = req.param('name'); console.log('passport의 local-signup 호출됨 : ' + email + ', ' + password + ', ' + paramName); …….

패스포트 설정 파일 불러오기 메인 파일에서 passport.js 파일 불러온 후 함수 실행 // 패스포트 설정 var configPassport = require('./config/passport'); configPassport(app, passport); …….

라우팅 함수를 위한 모듈 파일 만들기 routes 폴더 안에 user_passport.js 파일을 만들고 라우팅 함수 추가 module.exports = function(app, passport) { // 홈 화면 - 로그인 링크 router.route('/‘).get(function(req, res) { ……. }); // 로그인 폼 링크 router.route('/login‘).get(function(req, res) { var userPassport = require('./routes/user_passport'); userPassport(app, passport); …….

4. 페이스북으로 로그인하기 난이도 소요시간 20분

페이스북으로 로그인 방식 포털 사이트나 SNS 계정을 사용하는 로그인 방식을 많이 사용 OAuth 인증 기능 사용

페이스북 사이트에서 등록 페이스북 개발자 콘솔 창에서 애플리케이션 등록을 해야 사용 가능 ▶ https://developers.facebook.com/

페이스북 사이트에서 등록 페이스북 개발자 콘솔 창에서 애플리케이션 등록을 해야 사용 가능

생성된 정보를 설정에 추가 개발자 콘솔에서 생성한 App ID와 App Secret 정보를 config.js 파일에 추가 module.exports = { server_port : 3000, db_url : 'mongodb://localhost:27017/shopping', db_schemas : [ {file : './user_schema', collection : 'users6', schemaName : 'UserSchema', modelName : 'UserModel'} ], route_info : [ facebook : { clientID : 'OOOOOOOOOOOOO', clientSecret : 'OOOOOOOOOOOOOOOOOOOO', callbackURL : '/auth/facebook/callback' }, …….

패스포트 설정 파일에 추가 및 새로운 파일 생성 passport.js 파일에 추가 ……. var facebook = require('./passport/facebook'); module.exports = function (app, passport) { passport.use('facebook', facebook(app, passport)); }

페이스북을 위한 파일 생성 passport 폴더 안에 facebook.js 파일 생성 var FacebookStrategy = require('passport-facebook').Strategy; var config = require('../config'); module.exports = function(app, passport) { return new FacebookStrategy({ clientID : config.facebook.clientID, clientSecret : config.facebook.clientSecret, callbackURL : config.facebook.callbackURL }, function(accessToken, refreshToken, profile, done) { console.log('passport의 facebook 호출됨.'); console.dir(profile);

페이스북을 위한 파일 생성 passport 폴더 안에 facebook.js 파일 생성 var options = { criteria : {'facebook.id' : profile.id} }; var database = app.get('database'); database.UserModel.load(options, function (err, user) { if(err) return done(err); if(!user) { var user = new database.UserModel({ name : profile.displayName, email : profile.emails[0].value, provider : 'facebook', facebook : profile._json }); user.save(function(err) { if(err) console.log(err); return done(err, user);

모듈 설치하고 데이터베이스 스키마 변경 passport-facebook 모듈 설치 필요 스키마 변경 필요 % npm install passport-facebook --save var UserSchema = mongoose.Schema({ email : {type : String, 'default' : ''} , hashed_password : {type : String, 'default' : ''} , name : {type : String, index : 'hashed', 'default' : ''} , salt : {type : String} , created_at : {type : Date, index : {unique : false}, 'default' : Date.now} , updated_at : {type : Date, index : {unique : false}, 'default' : Date.now} , provider : {type : String, 'default' : ''} , authToken : {type : String, 'default' : ''} , facebook : { } });

라우팅 함수 추가 라우팅 함수 만든 후 설정에 추가 module.exports = function(app, passport) { ……. // 패스포트 - 페이스북 인증 라우팅 router.route('/auth/facebook').get(passport.authenticate('facebook', { scope : 'email' }) ); // 패스포트 - 페이스북 인증 콜백 라우팅 router.route('/auth/facebook/callback').get(passport.authenticate('facebook', { successRedirect : '/profile', failureRedirect : '/' }

홈 화면을 위한 웹페이지 수정 후 확인 index.ejs 파일의 코드 수정 후 웹브라우저에서 접속하여 확인 ……. <a href = "/auth/facebook" class = "btn btn-primary"> <span class = "fa fa-facebook"></span> 페이스북으로 로그인 </a>

프로필 페이지 수정 profile.ejs 파일 수정 ……. <% if(user.provider == undefined || user.provider == '') { %> <h3><span class = "fa fa-user"></span> 로컬 프로필</h3> <br> <p> <strong>이메일</strong> : <% = user.email %><br><br> <strong>별명</strong> : <% = user.name %> </p> <% } else if(user.provider == 'facebook') { %> <h3 class = "text-primary"> <span class = "fa fa-facebook"></span> 페이스북 프로필 </h3> <strong>아이디</strong> : <% = user.facebook.id %><br><br> <strong>이메일</strong> : <% = user.facebook.email %><br><br> <strong>이름</strong> : <% = user.facebook.name %> <% } %>

참고 문헌 [ References] 기본 서적 2017, 정재곤, “Do it! Node.js 프로그래밍 (개정판)”, 이지스퍼블리싱 Node.js Site http://nodejs.org/