소셜 로그인
: 소셜 네트워킹 사이트의 정보를 이용해 타사 애플리케이션과 플램폼에 손쉽게 로그인할 수 있는 프로세스
계정을 만들 필요 없이 편리한 방법을 제공하여 로그인 및 등록 경험을 간소화 할 목적으로 개발되었다.
이 때 사용되는 프로코콜이 OAuth
이다.
OAuth
: 인터넷 사용자들이 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여 할
수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준.
Resource Owner
: Resource 는 개인정보⇒ 웹 서비스를 이용하려는 유저,자원(개인정보)을 소유하는 자, 사용자
Client
⇒ 자사 또는 개인이 만든 애플리케이션 서버
⇒ 사용자(Resource Owner)
에게 필요한 자원을 요청하고 응답하는 관계
Authorization Server
⇒ 권한을 부여(인증)해주는 서버
⇒ 사용자(Resource Owner)
는 이 서버로 개인정보를 넘겨 Authorization Code
를 받을 수 있다.
⇒ Client
는 이 서버로 Authorization Code
를 넘겨 Token를 받을 수 있다.
페이지요청
: 사용자가 브라우저를 통해 서비스 접근 및 이용 시도
HTML코드
: 백엔드 API에서 유저에게 로그인 페이지 제공해주기
// auth Controller.ts
@UseGuards(AuthGuard('google'))
// 가드를 통과해주려면 google.strategy 를 작성해줘야한다.
@Get('/login/google')
async loginGoogle(
@Req() req: Request & IOAuthUser, //
@Res() res: Response, //
) {
//생략
}
로그인
: 사용자가 구글에게 로그인 요청
로그인정보(시크릿코드)
: 로그인 정보가 정상인지 확인 후 시크릿 코드 전송
5, 6. 로그인정보(시크릿코드)
: 사용자에게 보낸 시크릿코드를 다시 백엔드API로 보낸다음 백엔드API가 다시 구글에게 전송
: 로그인한 사용자가 일치하는지 확인하기 위해서!
// jwy-social-google.strategy.ts
// 4,5,6번 코드들은 다 PassportStrategy 내장되어 있음
export class JwtGoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor() {
super({
clientID: process.env.JWT_CLIENTID, // 이것들은 구글 클라우드 플램폼에서 받을수 있음
clientSecret: process.env.JWT_CLIENTSECRET,
callbackURL: 'http://localhost:3000/login/google',
scope: ['email', 'profile'],
});
}
accessToken / 프로필 정보
: 시크릿코드가 정상일 경우 구글에서 백엔드API에게 AccessToken / refreshToken / profile 전달
// jwy-social-google.strategy.ts
validate(accessToken, refreshToken, profile) {
console.log(accessToken);
console.log(refreshToken);
console.log(profile);
return {
name: profile.displayName,
email: profile.emails[0].value,
// hashedPassword
password: 'hashedPassword',
age: 0,
};
}
자체 서비스 자동 회원가입 / 로그인
: 백엔드API에서 회원가입을 검증하고 회원가입이 안되어있다면 회원가입 시킨뒤 로그인
(AccessToken / refreshToken 생성 및 발급)
// auth Controller.ts
//프로필을 받아온 다음, 로그인 처리해야 하는 곳
// 1. 회원조회
// 회원이 있으면 findOne 으로 찾아서 기다렸다가 유저 값을 반환한다.
let user = await this.usersService.findOne({ email: req.user.email });
// 회원이 없다면 회원등록하고 그 등록된 데이터를 유저에 담아준다.
// 2. 회원가입이 안돼있다면? 자동회원가입
if (!user) user = await this.usersService.create({ ...req.user });
// 3. 회원가입이 돼있다면? 로그인하기
// (refreshToken, accessToken 만들어서 브러우저에 전송)
this.authService.setRefreshToken({ user, res });
(여기서는 왜 자동회원가입이라고 했는지 이해가 안간다.. 이해가 안간다면 수정해서 다시 올리겠다)
로그인 완료 화면으로 페이지 이동(refreshToken 포함)
구글 개발자 도구를 보면 refreshToken 쿠키를 같이 보내주는 것을 확인 할수 있음.
// auth Controller.ts
// 2. html 코드 보내주기
@UseGuards(AuthGuard('google'))
// 가드를 통과해주려면 google.strategy 를 작성해줘야한다.
@Get('/login/google')
async loginGoogle(
@Req() req: Request & IOAuthUser, //
@Res() res: Response, //
) {
//프로필을 받아온 다음, 로그인 처리해야 하는 곳
// 1. 회원조회
// 회원이 있으면 findOne 으로 찾아서 기다렸다가 유저 값을 반환한다.
let user = await this.usersService.findOne({ email: req.user.email });
// 회원이 없다면 회원등록하고 그 등록된 데이터를 유저에 담아준다.
// 2. 회원가입이 안돼있다면? 자동회원가입
if (!user) user = await this.usersService.create({ ...req.user });
// 3. 회원가입이 돼있다면? 로그인하기
// (refreshToken, accessToken 만들어서 브러우저에 전송)
this.authService.setRefreshToken({ user, res });
// 9번 추가 작성
res.redirect(
'http://localhost:5500/class/section11/11-06-login-google/frontend/social-login.html',
);
}
}