Software Workshop

단계별 쿠키 처리 과정

config/express.js

  1. app.use(session(…))을 통해 connect.sid라는 쿠키 키가 등록됨
  2. session()은 express-session이라는 node moodule의 instance
  3. app.use(passport.initialize())와 app.use(passport.session())을 통해 패스포트가 미들웨어로 등록됨

node_modules/express-session/index.js

  1. session()에서 uid(random number)를 생성하고 req.sessionID에 기록함
  2. 이 값을 cookie signing(encryption) 과정을 거쳐 다음과 같은 쿠키를 만들어 냄
connect.sid=s2_BViuqciPgMdb9-7rjaWBjUc0Vd0dJv.xcpTrAHMnhYRgXFJBlvzbLyGvV2womKtCz0IVifGyqQ; path=/; domain=dev-mango.[[http://searchad.naver.com|searchad.naver.com]];

이렇게 signed cookie를 만드는 이유는 클라이언트에서 조작하지 못하도록 하기 위함임

{ 
  "_id" : "2_BViuqciPgMdb9-7rjaWBjUc0Vd0dJv", 
  "session" : "{\\"cookie\\":{\\"originalMaxAge\\":null,\\"expires\\":null,\\"secure\\":false,\\"httpOnly\\":true,\\"path\\":\\"/\\"},\\"passport\\":{}}", 
  "expires" : ISODate("2014-09-18T06:46:54.395Z") 
}
{ 
  "_id" : "2_BViuqciPgMdb9-7rjaWBjUc0Vd0dJv", 
  "session" : "{\\"cookie\\":{\\"originalMaxAge\\":null,\\"expires\\":null,\\"secure\\":false,\\"httpOnly\\":true,\\"path\\":\\"/\\"},\\"passport\\":{\\"user\\":\\"53fbe331559b79e51b5d47fa\\"}}", 
  "expires" : ISODate("2014-09-18T06:50:00.934Z") 
}

쿠키에 들어갈 사용자 정보를 기록하는 과정(local strategy)

  1. packages/access/server/config/passport.js
    • local strategy를 미들웨어로 등록함
      passport.use(new LocalStrategy(...));
    • strategy에 verify function으로 등록되는 함수가 다음과 같이 정의됨
function(email, password, done) { 
  User.findOne({ email: email }, function(err, user) { 
    if (err) { 
      return done(err); 
    } 
    if (!user) { 
      return done(null, false, { message: 'Unknown user' }); 
    } 
    if (!user.authenticate(password)) { 
      return done(null, false, { message: 'Invalid password' }); 
    } 
    console.log('passport.use() in access after user.authenticate()');
    return done(null, user); 
  }); 
}

여기서 email을 키로 해서 검색된 사용자 정보가 verify에 성공하면 세션에 등록할 사용자 정보가 됨

packages/users/server/routes/users.js

app.route('/login').post()에 등록되는 미들웨어 중 하나인 passport.authenticate()가 호출됨

node_modules/passport-local/lib/strategy.js

Strategy.prototype.authenticate()에서 verify()를 실행하여 사용자 password의 일치여부를 확인함
verified가 callback으로 호출되면서 self.success(user)를 호출하여 user 객체를 전달함

node_modules/passport/lib/middleware/authentiate.js

strategy.success()를 정의하면서 user 파라미터를 넘겨받게 되어 있는데, 이 값이 req.logIn() 호출에 사용됨
authenticate()에서 req.logIn()을 호출하는데 이 함수는 바로 node_modules/passport-oauth/node_modules/passport/lib/passport/http /request.js에서 정의되어 있음

node_modules/passport-oauth/node_modules/passport/lib/passport/http/request.js

req.logIn()에서 this._passport.instance.serializeUser()를 호출해서 req.session.passport.user의 값을 채워넣음

node_modules/passport/lib/authenticator.js

직렬화 함수로 Authenticator.prototype.serializeUser()가 호출되는데 여기서 user 객체를 직렬화하여 req.session.passport에 달아놓게 됨

코드 분석 중 발견된 문제점

  1. passport.js가 config 디렉토리와 packages/access/server/config 디렉토리에 각각 존재하는데 후자의 passport.js가 실제로 사용되고 있음
  2. local strategy를 사용하는데도 불구하고 node_modules/passport/lib/http/request.js가 사용되어야 하는데 node_modules/passport-oauth/node_modules/passport/lib/passport/http /request.js이 대신 사용되고 있음 (의존성 충돌)

결론