passport
passport는 세션을 내부적으로 처리해주는 패키지이다. 이 패키지를 이용하면 구글, 페이스북, 카카오톡 등 다양한 로그인 기능을 구현할 수 있다고 한다.
passport-local 을 설치해 준다.
npm install passport passport-local
npm install express-session
추가한 코드
var session = require('express-session'); ... app.use(session({ resave: false, saveUninitialized: false, secret: 'seccret code', cookie: { httpOnly: true, secure: false, }, }));
var flash = require('connect-flash'); ... app.use(flash());
주의할 점은 connecrt-flash 미들웨어는 cookie-parser와 express-session을 사용하므로,
이들보다는 뒤에 위치해야 한다.
usernameField 와 passwordField 는 어떤 폼 필드로부터
아이디와 비밀번호를 전달받을 지 설정하는 옵션이다.
body에 데이터가 { login_id: 'bi', login_pass: '1234' } 이렇게 오면
뒤의 콜백 함수의 id 값이 bi, password 값이 1234가 된다.
session 은 말 그대로 세션을 사용할 지 안 할 지를 선택한다.
passReqToCallback은 true로 해두면 뒤의 콜백이 (req, id, password, done) => {}; 으로 바뀐다.
id 매개변수 앞에 req 매개변수가 추가되었으며, req를 통해서 express의 req 객체에 접근할 수 있다.
passReqToCallback을 true로 해 두면 req 객체를 passport 인증 시 활용할 수 있다.
false로 해야할지 true로 해야할지는 추후 방향을 정해야겠다.
아이디와 비밀번호 값이 들어오면 뒤의 콜백 함수가 실행되는데,
id로 유저를 찾은 후, 유저가 없으면 존재하지 않는 아이디라고 에러를 보낸다.
유저가 있다면, 비밀번호를 비교해서 비교 과정에서 서버 에러가 나면
done (findError) 으로 에러를 리턴하고 ,
비밀번호가 맞을 경우 done(null, user); 로 user 객체를 전송해주고,
틀렸을 경우는 비밀번호가 틀렸다고 done(null, false, { message: '에러메시지' })로 메시지를 전송한다.
첫 번째 인자는 DB조회 같은 때 발생하는 서버 에러를 넣는 곳이다.
무조건 실패하는 경우에만 사용한다.
두 번째 인자는 성공했을 때 return할 값을 넣는 곳이다.
성공했으면 첫 번째 인자는 null이어야한다. 에러가 있으면 안되기 때문이다.
세 번째 인자는 사용자가 임의로 실패를 만들고 싶을 때 사용한다.
첫 번째 인자를 사용하는 경우는 서버에서 에러가 났을 때 무조건 실패하는 경우이며,
세 번째 인자는 위에서 비밀번호가 틀렸다는 에러를 표현하고 싶을 때 사용하면 된다.
이것은 서버 에러도 아니고, 사용자가 임의로 만드는 에러이기 때문에, 직접 에러 메시지도 써준다.
serializeUser은 로그인 성공 시 실행되는 done(null, user);에서
user 객체를 전달받아 세션(req.session.passport.user)에 저장한다.
세션이 있어야 페이지 이동 시에도 로그인 정보가 유지될 수 있다.
deserializeUser은 실제 서버로 들어오는 요청마다
세션 정보 ( serializeUser에서 저장 ) 를 실제 DB의 데이터와 비교한다.
해당하는 유저 정보가 있으면 done의 두 번째 인자를 req.user에 저장하고,
요청을 처리할 때 유저의 정보를 req.user를 통해서 넘겨준다.
하지만 위의 코드에서는 아무런 처리과정 없이 (세션에는 저장) 그냥 넘겨주는 상태이다.
serializeUser에서 done으로 넘겨주는 user가
deserializeUser의 첫 번째 매개변수로 전달되기 때문에 둘의 타입이 항상 일치해야 한다.
만약 serializeUser에서 id만 넘겨줬다면 deserializeUser의 첫 번째 매개변수도 id를 받아야 한다.
id만 있으면 그 자체로는 req.user을 만들 수 없기 때문에
User.findById(id) 메소드로 완전한 user 객체를 만들어서 done을 해주면 된다.
passport가 어떻게 동작하는지 정도는 조금 알 것 같은데 ㅠㅠ
실제 적용하려면 머리를 좀 더 써봐야 할 것 같다 ..