passport-oauth2 (feat: passport-apple)

오픈소스·2023년 10월 2일
0
post-thumbnail

  • passport-oauth2에 의존적인 packages
    • passport-kakao
    • passport-google-oauth20
    • passport-apple

https://github.com/youngkiu/nestjs-kakaologin/blob/main/src/auth/google/google.strategy.ts
다른 여타의 passport-oauth2와 다르게, validate() method를 구현하지 않으며,
(response_type=code%20id_token이기 때문이며, response_type=code이면 구현해야 한다.)
다른 여타의 passport-oauth2의 validate()에서 하는 역할을 constructor의 callback으로 제공한다.

https://github.com/ananay/passport-apple

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { JwtService } from '@nestjs/jwt';
import { Strategy } from 'passport-apple';
import { PinoLogger } from 'nestjs-pino';
import { readFileSync } from 'fs';
import { AppleUserDataDto } from './apple_user_data.dto';
import { UserService } from '../../user/user.service';
import { CreateUserDto } from '../../user/create_user.dto';

@Injectable()
export class AppleStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly configService: ConfigService,
    private readonly jwtService: JwtService,
    private readonly userService: UserService,
    private readonly logger: PinoLogger,
  ) {
    logger.setContext(AppleStrategy.name);

    super(
      {
        clientID: configService.get<string>('APPLE_CLIENT_ID'),
        teamID: configService.get<string>('APPLE_TEAM_ID'),
        callbackURL: configService.get<string>('APPLE_CALLBACK_URL'),
        keyID: configService.get<string>('APPLE_KEY_ID'),
        privateKeyString: readFileSync(
          configService.get<string>('APPLE_KEYFILE_PATH'),
        ),
        passReqToCallback: true,
      },
      async function (req, accessToken, refreshToken, idToken, profile, cb) {
        try {
          const idTokenDecoded = jwtService.decode(idToken) as AppleUserDataDto;
          logger.debug(JSON.stringify(idTokenDecoded));

          const provider = 'google';
          const { sub: providerId, email } = idTokenDecoded;

          const user = await userService.find(provider, providerId);
          if (user) {
            return cb(null, user);
          }

          const userData: CreateUserDto = {
            provider,
            providerId,
            email,
            profile: idTokenDecoded,
            accessToken,
            refreshToken,
          };
          await userService.create(userData);
          cb(null, userData);
        } catch (error) {
          logger.error(error);
        }
      },
    );
  }
}

참고)

0개의 댓글