이번에 소셜로그인을 진행하면서 카카오, 네이버, 구글로 로그인이 가능하게 만들기로 했다. 다들 oauth 로그인을 해보고싶다고 해서, 나는 구글로그인만 하기로 결정됐다.
나머지 oauth 중에 구글로그인이 좀 까다롭다고 해서 걱정했는데, 우여곡절이 있긴 했지만 나름 선방했다.
순서는 아래와 같다.
token발급을 서버에서 하는 이유는 보안상의 이유 때문이다.
const handleSignGoogle = () => {
window.location.assign(
`https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.REACT_APP_GOOGLE_CLIENT}&redirect_uri=${process.env.REACT_APP_REDIRECT_URL}/googlecallback&response_type=code&scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email&state=google`
);
};
구글에서 내앱을 설정하고 부여받은 clientid와 설정한 redirecurl을 파라미터로 담아 google oauth2에 보내준다.
const navigate = useNavigate();
const url = new URL(window.location.href);
const authorizationCode = url.searchParams.get('code');
const dispatch = useDispatch();
useEffect(() => {
googleOauth(authorizationCode).then((res) => {
console.log(res);
dispatch(oauthLogin());
navigate(-1);
});
}, [authorizationCode, navigate, dispatch]);
페이지가 렌더링 될 때 url에 파라미터로 보내진 code를 찾아 서버에 전달해준다.
google: async (req, res) => {
const accessCode = req.body.authorizationCode;
const oauth2Client = new google.auth.OAuth2(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
process.env.REDIRECT_URL
);
const { tokens } = await oauth2Client.getToken(accessCode);
oauth2Client.setCredentials(tokens);
const userInfo = await axios.get(
`https://www.googleapis.com/oauth2/v3/userinfo?access_token=${tokens.access_token}`
);
const { sub, email, picture } = userInfo.data;
user
.findOrCreate({
where: { userId: sub, email: email },
defaults: { userId: sub, email: email, image: picture },
})
.then(([data, created]) => {
const accessToken = generateAccessToken(data.dataValues);
sendAccessToken(res, accessToken);
return res.status(201).json({ success: true, message: '로그인이 완료되었습니다' });
})
.catch((err) => console.log(err));
},
oauth2Client 객체를 생성하고, getToken메소드를 사용하여 accessCode를 보내 tokens를 받아온다.
oauth2Client에 setCredentails(tokens)로 토큰을 넣러준 후, google oauth2에 유저 정보 get요청을 보낸다.
유저정보가 받아지면, DB에 저장하고 우리 서버의 accessToken을 만들어준 다음, 보내주면 된다.
구글로그인 버튼을 만들어주었기 때문에, 다른 사람들이 사용하는 라이브러리는 사용할 수 없었다. 그래서 클라이언트와 서버 작업을 나누어서 해줬는데, 레퍼런스가 많이 없어서 조금 헤맸다.
tokens 안에 있는 access_token을 넣어줘야 하는데, tokens를 넣어서 에러가 나기도 했다. 구글링 후 tokens 안에 있는 access_token을 담아서 get요청을 보내야 한다는 걸 알고 고쳐주었다.