[NestJS] Passport 소셜 로그인 시 리다이렉트

정도영·2024년 2월 17일
0
post-thumbnail

개요

유저의 권한이 요구되는 페이지에 접속한다면, 미들웨어를 이용해서 로그인 페이지로 보냈다.

일반 로그인은 로그인 요청을 보내서 로그인이 성공한다면, 유저가 접속하려고 했던 페이지로 리다이렉트 시켰지만, OAuth2 방식의 소셜 로그인의 경우에는 로그인을 성공하면, 해당 소셜의 자체 url로 리다이렉트 시키기 때문에 로그인이 성공한 경우 유저가 접속하려고 했던 url을 가지고 있어야 했다.

처음에는 Redis를 사용해서이걸 하려고 Redis나 DB에 따로 저장을 하는 건 너무 효율이 떨어진다고 생각해서 코드에서 최대한 수정하려고 했다.

https://devtalk.kakao.com/t/rest-api/127681 이 글을 통해 다른 방법을 이용할 수도 있겠다.

코드

프론트

const googleLoginHandler = () => {
    window.location.href = `${process.env.NEXT_PUBLIC_BASE_URL}/auth/google/redirect?from=${from}`;
  };

프론트 측에서는 다음과 같은 action으로 소셜 로그인 요청을 보낸다

// google-auth.controller.ts
@Get('/redirect')
@UseGuards(GoogleAuthGuard)
async handleRedirect(@Req() req: any, @Res() res: Response) {
	
    ... 

	if (req.redirect !== 'undefined') {
      return res.redirect(`${process.env.CLIENT_URL}/${req.redirect}`);
    } else {
      return res.redirect(`${process.env.CLIENT_URL}`);
    }
    
}

백에서는 다음과 같이 API 요청을 받고 있는데, 여기서 @Param을 from으로 받아도 GoogleAuthGuard에 의해서 소셜 로그인이 성공한다면, 자체 리다이렉트 url로 와서 param이 없어지게 된다. 그래서 guard에 접근할 때, 파라미터로 받은 from을 저장하는 것이 포인트다.

// google-auth.guard.ts
import { ExecutionContext, Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class GoogleAuthGuard extends AuthGuard('google') {
  constructor() {
    super();
  }

  private static activate = false;
  private static redirect;

  async canActivate(context: ExecutionContext) {
    if (!GoogleAuthGuard.activate) {
      GoogleAuthGuard.redirect = context.switchToHttp().getRequest().query.from;
      GoogleAuthGuard.activate = true;
    }

    const activate = (await super.canActivate(context)) as boolean;
    const request = context.switchToHttp().getRequest();
    context.getArgs()[0]['redirect'] = GoogleAuthGuard.redirect;

    await super.logIn(request);
    GoogleAuthGuard.activate = false;
    return activate;
  }
}

여기서 중요했던 건, canActivate를 재귀함수로 부르기 때문에 redirect가 다시 초기화돼서 undefined로 바뀌어서, 이부분을
private static activate = false;
private static redirect;
두 개의 클래스 변수로 빼주어서 프론트에서 전달된 from 즉, redirect url이 초기화 되지 않도록 했다.

그리고, context.getArgs()[0]['redirect'] = GoogleAuthGuard.redirect; 이 변수를 이용해서 context에 redirect를 추가해주었다.

그러면 컨트롤러의 handleRedirect 함수에 들어와도 req.redirect 이 변수를 이용해서 프론트에서 받은 url로 리다이렉트 할 수 있다!!

후기

역시 혼자하려니 힘드러 ~.. ㅠㅠ

profile
대한민국 최고 개발자가 될거야!

0개의 댓글