요즘 웹 서비스에서 필수적인 요소인 소셜로그인 대표적으로 구글,카카오,네이버,페이스북이 존재하며
프로세스가 어떻게 작동하는지 알아보자
1.구글로그인 버튼을 눌러 페이지를 요청한다.
2.백엔드 api에서는 소셜로그인을 시도하는 유저에게 소셜미디어의 HTML코드를 넘겨준다
3.유저는 받은 HTML에서 본인이 로그인하고 싶은 사용자를 선택하고, 그러면 소셜미디어로 로그인을 하게됨
4.소셜미디어에서 올바르게 로그인을 하게되면 브라우저로 시크릿코드를 보내준다
5.브라우저에서는 시크릿코드를 백엔드서버로 보내준다
6.백엔드서버는 이 시크릿코드를 소셜미디어에 다시 보내면서 ‘니가 보낸 시크릿코드가 이게 맞나?’ 하면서 물어본다
7.소셜미디어에서 확인해보고 일치하면 accessToken과함께 유저 프로필을 보내준다.
8.백엔드서버에서는 받아온 프로필로 정보가 없으면 회원가입으로 보내고, 있으면 로그인을 완료시킨다
대표적으로 구글 로그인의 코드를 간략하게 살펴보자
// controller
import {
Body,
Controller,
Get,
Post,
Req,
Res,
UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Request, Response } from 'express';
import { IOAuthUser } from '../users/interfaces/users-service.interface';
import { UsersService } from '../users/users.service';
import { AuthService } from './auth.service';
@Controller()
export class AuthController {
constructor(
private readonly usersService: UsersService, //
private readonly authService: AuthService,
) {}
@UseGuards(AuthGuard('google'))
@Get('/login/google')
async loginGoogle(
@Req() req: Request & IOAuthUser, //
@Res() res: Response,
) {
this.authService.socialLogin({ req, res });
}
}
api 요청이 들어오면 가드를 통해 인증을 거쳐야 한다 인증이 통과 시 로직이 실행된다
인증을 거치기위한 로직이 담긴 파일을 하나 만들어야 하며
구글 로그인 라이브러리를 설치해야 한다
yarn add passport-google-oauth20 으로 설치해준다.
ts도 설치해줘야하기때문에 yarn add --dev @types/passport-google-oauth20 도 설치해주어야함
// jwt-social-google.strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-google-oauth20';
export class JwtGoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor() {
super({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: 'http://localhost:3000/login/google',
scope: ['email', 'profile'],
});
}
validate(accessToken, refreshToken, profile) {
return {
user_name: profile.displayName,
user_email: profile.emails[0].value,
user_address: 'social',
user_phone: 'social',
user_pwd: 'social',
user_ssn: 'social',
};
}
}
가드를 통해 들어온 요청을 인증하는 파일로 생성자(constructor) 부분에서 시크릿코드를 보내어 인증하는 부분이다
인증이 완료되면 validate로 구글에게 전달받은 유저 정보를 받아오게 되며 가드를 요청한 곳으로 값을 리턴해주게 된다
// service
async socialLogin({ req, res }: IAuthServiceSoicalLogin) {
// 1.회원조회
let user = await this.usersService.findOneByEmail({
user_email: req.user.user_email,
});
// 2. 회원가입이 안돼있다면? 자동회원가입
if (!user) {
const createUserInput = { ...req.user };
user = await this.usersService.create({ createUserInput });
}
// 3. 회원가입이 돼있다면? 로그인(refreshToken, accessToken 만들어서 브라우저에 전송)
this.setRefreshToken({ user, res });
res.redirect(
'http://localhost:5500/main-project/frontend/login/index.html',
);
}
setRefreshToken({ user, res }: IAuthServiceSetRefreshToken): void {
const refreshToken = this.jwtService.sign(
{ id: user.user_id },
{ secret: process.env.JWT_REFRESH_KEY, expiresIn: '2w' },
);
res.setHeader('set-Cookie', `refreshToken=${refreshToken}; path=/;`);
}
인증이 완료되어 전달받은 정보로 회원가입이 되어있지 않다면 회원가입을 진행하고
되어있다면 토큰을 만들어 브라우저에 전송 해준다!