로그인을 하면, serialize 를 통해서 authId 값이 파일형태로 저장된다.

세션은 파일에 저장돼서 살아있으나, 사용자의 회원정보는 users 라는 배열에 저장하고있기 때문에, 메모리상에 존재하는 데이터는 애플리케이션을 끄면 사라지게 된다.

세션 정보는 살아있는데, 사용자의 정보는 없어져있는 상태이다.

deserializeUser 의 for 문을 타지만, 해당하는 값이 없기 때문에 무한 반복을 하게된다.

이러한 경우가 발생했을 때, 인지하기 위해서, deserializeUser 에 해당 코드를 추가해준다.

// 로그인을 해놓고 꺼버리면, 세션을 파일형태로 저장되어있는데,파일 형태로 저장되어있는 세션을 계속해서 가져오려고하는데
// users 가 없어서 계속 반복되는 문제가 발생한다.
// 이럴 때는 세션을 지워버리면 가능하다.
passport.deserializeUser(function(id, done) {
  console.log('deserializeUser', id);
  for (var i = 0; i < users.length; i++) {
    var user = users[i];
    if (user.authId === id) {
      return done(null, user);
    }
  }
  //에러 메세지를 출력한다.
  //파일에 세션이 저장되어있어서 세션은 지워지지 않지만, user 배열은 메모리성 이기 때문에
  //사라지게 된다.
  //그렇기 때문에, 세션 파일을 지워버리면 해결이된다.
  done('There is no user.');
});

또한 새롭게 생성하는 페이스북 전략에서 profile 인자에 들어갈 구체적인 데이터를 명시적으로 표현할 수 있다.

여기에 앞으로 사용할, email, displayname은 반드시 들어가야한다.

// 새로운 페이스북 전략을 사용한다.
passport.use(new FacebookStrategy({
    // 페이스북 새로운 ID 를 입력한다.
    clientID: '1713107952186927',
    // 시크릿 코드를 입력.
    clientSecret: '6c5a3f43030ec9067d917b46b0d557b1',
    // 페이스북을 활용할 때는, 콜백 URL 을 사용해야한다.
    callbackURL: "/auth/facebook/callback",
    // profile 에 들어갈 값을 명시적으로 표현할 수 있다.
    // 여기에 email,displayname을 넣어야한다.
    profileFields:['id', 'email', 'gender', 'link', 'locale', 'name', 'timezone', 'updated_time', 'verified', 'displayName']
  },
  //만약 사용자가 있다면, done 이라는 함수의 인자로 사용자의 정보를 보내주는 함수
  function(accessToken, refreshToken, profile, done) {
    // console.log 를 통해서 profile에 무엇이 들어가있는지 확인해보자.
    console.log(profile);
    //페이스북 상에서의 id 값을 가져와야한다. (굉장히 중요한 요소)
    // 페이스북으로 인증한 사용자이기 때문에, facebook 과 식별값인 profile.id 를 가져온다.
    var authId = 'facebook:' + profile.id;
    // user 객체로 넣을 객체 배열을 정의한다.
    // 사용자가 이미 존재하다면, 추가할 필요가 없기 때문에 존재한지 먼저 파악해야한다.
    for (var i = 0; i < users.length; i++) {
      var user = users[i];
      // user 객체에 authid 값과 현재 로그인할때의 authId 과 같다면,
      // 이미 존재한 사용자이다.

      if (user.authId === authId) {
        // 이미 user 객체에 사용자가 있을 때
        // done 의 두 번째 인자로 user가 들어가면, 이미 존재한 유저라는 것을 의미한다.
        return done(null, user);
      }
    }
    // user 객체에 사용자가 없다면
    var newuser = {
      'authId': authId,
      // local과 facebook 둘 다 displayName 이 똑같은 요소로 들어가고있다.
      'displayName': profile.displayName,
      //username 으로 계속해서 식별을 했는데, 이제는 authId를 통해서 식별을 해야한다.
      //그렇게 되면, 어떤 값을 식별값으로 해야할지 정해야하는데, 우리는 authId 로 통일한다.
      // 이메일을 통해서 사용자에게 인증을 시켜서 사용할 수 있기 때문에 email 이 좋다.
      'email':profile.emails[0].value
    };
    users.push(newuser);
    // 새로운 사용자를 보내서, serializeUser 를 실행한다.
    done(null, newuser);
  }
));

또한 user 가 없다면 새로 만드는 newuser에는 email 값으로, profile.emails[0].value 의 값을 정의한다.

(profile)

{
  id: '3013299475421902',
  username: undefined,
  displayName: '김지훈',
  name: { familyName: '김', givenName: '지훈', middleName: undefined },
  gender: undefined,
  profileUrl: undefined,
  emails: [ { value: '[email protected]' } ],
  provider: 'facebook',
  _raw: '{"id":"3013299475421902","email":"kks1342320\\\\u0040hanmail.net","last_name":"\\\\uae40","first_name":"\\\\uc9c0\\\\ud6c8","name":"\\\\uae40\\\\uc9c0\\\\ud6c8"}',
  _json: {
    id: '3013299475421902',
    email: '[email protected]',
    last_name: '김',
    first_name: '지훈',
    name: '김지훈'
  }
}

emails 의 값을 가져올 수 있도록 코드를 작성한다.