📚 시작하기 전에..
한동안 기술 블로그를 쓰지 않은 이유는, 블로그 이전에 대한 고민이 많았다.
결론부터 말하면 노션으로 블로그를 작성한 후 이를 배포하는 방식을 사용할 예정이다.
하지만 지금 시험기간이라 할 시간도 없고, 이전에도 프로젝트 업보빔으로 인해 너무 바빴어서 방중에 배포 예정이다.
우선적으로, 노션에 적어놓은 내용들을 하나둘씩 올려볼까 한다..!
💡 시작하기
GDG 협업 스프린트 챌린지에서 구글 로그인을 구현하는 역할을 맡았다.
원래는 @react-oauth/google 라이브러리를 사용하여 구글 로그인을 구현했었다.
근데 사용해봤으면 알겠지만, 라이브러리를 사용하면 구글에서 넘겨주는 response가 정해져 있다.
우리 프로젝트에서는 백엔드에서 보내주는 별도의 response가 필요했기에, 라이브러리가 아닌 리디렉션을 활용하여 구현했다.
망할 구글 로그인… 6시간 동안 오류 해결하다가 죽는 줄
구글에서 설정한 client id와 redirect uri 적용하기
const G_CLIENT_ID = import.meta.env.VITE_APP_GOOGLE_CLIENT_ID;
const G_REDIRECT_URI = import.meta.env.VITE_APP_GOOGLE_REDIRECT_URI;
const googleURL = `https://accounts.google.com/o/oauth2/auth?client_id=${G_CLIENT_ID}&redirect_uri=${G_REDIRECT_URI}&response_type=code&scope=profile email`;
우선 구글 로그인을 적용할 페이지에 client id와 redirect uri를 사용하여 google의 url을 만들었다.
- redirect uri는 반드시 프론트와 서버 둘을 통일시켜야 함! ( ex)localhost:5173 )
const handleGoogleLogin = () => {
window.location.href = googleURL;
};
...
<S.LoginButton onClick={handleGoogleLogin}></S.LoginButton>
google 리다이렉트를 버튼에 적용해주었다.
random state 생성하기
state는 CSRF를 방지하기 위해 승인 요청과 응답 간의 상태를 유지하는 것이라고 한다.
CSRF? Cross-Site-Request-Forgery의 줄임말이다. 웹 애플리케이션 취약점 중 하나로 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 해서 특정 웹 페이지를 보안에 취약하게 한다거나 수정, 삭제 등의 작업을 하게 만드는 공격 방법이다.
분명 google developer에서는 state가 권장이지 필수는 아니라고 해서 안 했는데, state에 값을 넣어주지 않으니까 오류가 나더라.. 심지어 구글링을 해서 다른 사람들의 구현 방식을 봐도, state를 넣어서 하는 사람들은 아무도 없었었다.. 우리꺼만 그랬나.. ㅜㅜㅜㅜ 암튼 그래서 쿼리 파라미터로 인가코드와 함께 서버에 전달해주었다.
서버에서 그냥 프론트 측에서 state를 랜덤하게 생성해서 보내주면 된다고 해서 진짜 state를 랜덤으로 생성하는 함수 하나 만들었다.
const generateState = () => {
// 16바이트의 랜덤 값을 생성하고 이를 16진수 문자열로 변환
return Array.from(window.crypto.getRandomValues(new Uint8Array(16)))
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("");
}
이 함수와 함께 리다이렉팅되는 페이지에 api 구현도 해주었다
const getGoogleLogin = async () => {
const state = generateState();
try {
const res = await axios.get(
`${SERVER_URL}/auth/callback?state=${state}&code=${code}`
);
console.log(res);
const accessToken = res.data.access_token;
const userName = res.data.user_info.name;
const userId = res.data.user_info.id;
localStorage.setItem("accessToken", accessToken);
localStorage.setItem("userName", userName);
localStorage.setItem("userId", userId);
navigate("/main");
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getGoogleLogin();
}, []);
요렇게 하면 연결 끝!
(시연 영상을 올리려고 했으나, 당시에 찍어놓는 것을 깜빡했다...ㅜ)
🔗 참고
https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow?hl=ko
'React' 카테고리의 다른 글
[React] useRef로 Tab 구현하기 (1) | 2024.12.04 |
---|---|
[React] state 업데이트 큐 (0) | 2024.12.04 |
[React] lazy loading (2) | 2024.10.01 |
[React] React Hooks (0) | 2024.09.18 |
[React] Vite 사용하기 (1) | 2024.09.07 |