[DimeloProject]passport-github scope電子メールは存在しません


https://velog.io/@suyeonpi/Dimelo-Project-passport-local-google-github-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84-nest.js
以前のプッシュでpassportを使ってgithubログインを実現しました.
古いコード:
@Injectable()
export class GithubStrategy extends PassportStrategy(Strategy, 'github') {
  constructor(private authService: AuthService) {
    super({
      clientID: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_SECRET,
      callbackURL: 'http://localhost:3000/api/auth/github/callback',
      scope: ['user:email'], // user의 email에 접근가능하는 권한
    });
  }

  async validate(
    _accessToken: string,
    _refreshToken: string,
    profile: any,
    done: VerifyCallback,
  ): Promise<any> {
    const { id, avatar_url, name, email } = profile._json;
// 깃헙에서 반환하는 profile._json에서 필요한 정보 빼서 새로운 객체 만듬
    const githubUser: GithubLoginUserDto = {
      githubId: +id,
      email,
      imageUrl: avatar_url,
    };
    const user = await this.authService.githubSignUp(githubUser);
// 새로운 만든 객체를 바탕으로 새로운 user 만들고 해당 user를 done해서 serialize한다
    done(null, user);
  }
}
GitHubが返すprofileでgithubId、email、avatar urlを使用して新しいユーザを作成します.
しかしprofileではemailを返さないという問題があります.

元々ハブ設定ではpublic emailを設定しないとemailは返されません.
私はpublic emailを設定しましたが、もちろん電子メールを返すと思っていましたが、新しく口座を開設した後はpublic emailを設定しておらず、ログイン後はemailを返していないことに気づき、会員登録ロジックでエラーが発生しました.
Googleはもちろんemailを返すので問題ありませんがgithubはemailを返さないかもしれません.そのため、会員加入の論理を修正せざるを得ない.
Eメールがない機能アイテムのログインは、ログインに成功した後にEメール値を受信する可能性があります...会員に素早く加入したいユーザーはOuthログインするので、もう一度メール値を検証するのは会員に素早く加入したいユーザーには不便だと思います.
したがって、電子メールを持たないユーザは、Null形式で電子メールを受信することができる.
私たちのサイトでは、emailはそんなに重要な要素ではありませんから.Emailは、当サイトに会員を登録しているユーザーのみに使用されますが、auth会員はemailを必要とせずにログインできます.また、emailを持たないユーザはgithubIdを使用してユーザを問合せできるため、ユーザのemailをnullableに変更する.
以降メールを登録したい会員がいない場合、プロファイルの変更ページでメールをバインドできますか?聖書を作るのも一つの方法だと思います.
修正されたコード:
// github.strategy.ts
  async validate(
    _accessToken: string,
    _refreshToken: string,
    profile: any,
    done: VerifyCallback,
  ): Promise<any> {
    const { id, avatar_url, email } = profile._json;
    const githubUser: GithubLoginUserDto = {
      githubId: +id,
      email: email ? email : null, // 이메일이 없을 경우 null
      imageUrl: avatar_url,
    };
    const user = await this.authService.githubSignUp(githubUser);
    done(null, user);
  }
async githubSignUp(user: GithubLoginUserDto) {
   const foundGithub = await this.usersRepository.findOne({
     where: { email: user.email, githubId: user.githubId, deletedAt: null },
     select: ['id', 'email', 'nickname', 'imageUrl'],
   });

   if (foundGithub) {
     return foundGithub;
   }

   if (user.email) {
     // 이메일이 있는 경우, 유저테이블에 같은 이메일이 있는 경우 깃허브 아이디 연동
     const found = await this.usersRepository.findOne({
       where: { email: user.email, deletedAt: null },
     });

     if (found) {
       found.githubId = user.githubId;
       const { id, email, nickname, imageUrl } =
         await this.usersRepository.save(found);
       return {
         id,
         email,
         nickname,
         imageUrl,
       };
     }
   }

   const { id, email, nickname, imageUrl } = await this.usersRepository.save(
     user,
   );
   return { id, email, nickname, imageUrl };
 }