구글에서 profile, email, name등의 정보를 받아오는데 성공했다.
이제 토큰을 발급할 차례이다. 먼저 구글 이메일로 유저를 조회하고 이메일로 가입된 유저가 존재하면 토큰을 발급하여 로그인시키고, 없다면 회원가입을 시킨 후에 토큰을 발급할 것이다.
@Injectable()
export class AuthService {
constructor(
@InjectRepository(Member)
private memberRepository: Repository<Member>,
private jwtService: JwtService,
) {}
async findByEmailOrSave(email: string, fullName: string, photo: string, provider: string): Promise<Member> {
try {
const foundMember = await this.memberRepository.findOne({ where: { email } });
if (foundMember) return foundMember;
const newMember = this.memberRepository.save({
email,
name: fullName,
nickname: fullName,
profileImage: photo,
provider,
});
return newMember;
} catch (error) {
throw new Error('사용자를 찾거나 생성하는데 실패하였습니다');
}
}
async googleLogin(req): Promise<any> {
const { email, firstName, lastName, photo, provider } = req.user;
const fullName = firstName + lastName;
const member: Member = await this.findByEmailOrSave(email, fullName, photo, provider); // 이메일로 가입된 회원을 찾고, 없다면 회원가입
// JWT 토큰에 포함될 payload
const payload = {
id: member.id,
email: member.email,
nickname: member.nickname,
name: member.name,
isAdmin: member.isAdmin,
profileImage: member.profileImage,
};
return { access_token: this.jwtService.sign(payload, { expiresIn: process.env.JWT_ACCESS_EXPIRATION_TIME, secret: process.env.ACCESS_SECRET_KEY }) };
}
}
@Controller('auth')
export class AuthController {
constructor(private readonly loginService: AuthService) {}
@Get('google/login') // 구글 로그인으로 이동하는 라우터 메서드
@UseGuards(AuthGuard('google'))
async googleAuth() {}
@Get('oauth2/redirect/google')
@UseGuards(AuthGuard('google'))
async googleAuthRedirect(@Req() req, @Res() res) {
const token = await this.loginService.googleLogin(req);
res.cookie('access_token', token.access_token, { httpOnly: true });
res.redirect('/');
}
}
이전 게시글에서는
@Get('oauth2/redirect/google')로 리디렉션 후 가드에서 validate메서드가 실행되고
req의 user객체에 구글에 로그인한 유저의 정보가 전달됐다. AuthService에 googleLogin과 findByEmailOrSave 메서드를 작성한다.
@Entity()
export class Member {
@PrimaryGeneratedColumn({ type: 'bigint' })
id: number;
@Column()
email: string;
@Column()
name: string;
@Column()
nickname: string;
@Column({ nullable: true })
@IsOptional()
password: string;
@Column()
profileImage: string;
@Column({ nullable: true })
@IsOptional()
tel: string;
@Column({ nullable: true })
@IsOptional()
address: string;
@Column({ nullable: true })
@IsOptional()
subAddress: string;
@Column({ default: false })
isAdmin: boolean;
@Column({ default: 'none' })
provider: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@DeleteDateColumn()
deletedAt: Date;
// 관계 설정 코드 생략
}
이렇게 우리 서비스에 소셜 로그인을 추가해보았다. 만약 구글에서 받은 정보 외에 추가 정보가 필수적인 서비스라면 추가 정보를 입력받는 과정을 추가하여 회원가입을 시킬 수 있다.