Google Cloud Platform에서 OAuth 설정 먼저하자
구글 클라우드 콘솔에서는 OAuth 동의화면과 사용자 인증 정보를 등록해야 한다.
OAuth 동의화면
먼저 OAuth 동의화면에서는 앱 이름, 사용자 지원 이메일과 로고 등을 설정한다.
다음은 범위(scope)를 설정해야 한다. OAuth2를 사용하여 유저 정보에 접근 할텐데 어떤 정보에 접근 할지 알아야 한다. 추후 쿼리 날릴 때 파라미터로 날려야하므로 기억하자
마지막으로, 테스트 사용자에 자신이 사용할 email을 미리 등록한다. 팀원들이 있다면 팀원들도 등록해주자.
사용자 인증 정보
구글 클라우드 콘솔의 API 및 서비스 - 사용자 인증 정보 - OAuth2.0 클라이언트 ID에서 계정을 하나 생성해주자.
사용자 인증 정보에 등록하는 이유는 OAuth2 접근 할 때 client Id와 Redirect URI가 필요하다.
처음 클라이언트 ID를 선택하면, 클라이언트 종류를 고르는 메뉴가 나올텐데 자신이 개발하는 항목에 맞춰 골라주자
난 프론트니까 당연히 웹 애플리케이션으로 설정했다.
승인된 자바스크립트 원본에는 데이터를 요청하는 URI을 적어주자
Docs에 따르면 웹 애플리케이션을 호스팅하는 HTTP 원본이라, 이 값에는 와일드 카드나 경로를 포함하면 안된다. 80 외의 포트를 사용하는 경우 포트를 지정해주자.
예: https://example.com:8080
승인된 리디렉션 URI는 사용자 인증이 끝나면, 리다이렉팅 할 URI이다.
프론트 코드 처리
react-google-login 라이브러리를 쓰면 쉽게 구현 할 수 있었는데, Google에서 지원을 안할거란 이야기가 있어서 @react-oauth/google를 사용했다.(2023.03.31까지 마이그레이션 끝내라 공지도 하는데, 지금 시점으로 한 달 남은게 웃프다)
원래 계획은 클라이언트에서 token까지 모두 받는 것을 생각했는데, @react-oauth/google에선 클라이언트가 인증 코드만 처리하는 구조를 추천하기에 수정했다
최종 코드는 아래와 같다. 클라이언트에서는 인증 코드만 받아서, 이를 우리의 백엔드 서버로 보내 토큰을 돌려 받는 구조이다.
import { Box, Button } from "@mui/material";
import { useGoogleLogin } from "@react-oauth/google";
import axios from "axios";
const Login = () => {
const googleSocialLogin = useGoogleLogin({
scope: "email profile",
onSuccess: async ({ code }) => {
axios
.post("http://localhost:4000/auth/google/callback", { code })
.then(({ data }) => {
console.log(data);
});
},
onError: (errorResponse) => {
console.error(errorResponse);
},
flow: "auth-code",
});
return (
<Box>
<Box>
<Button onClick={googleSocialLogin}>Google Button</Button>
</Box>
</Box>
);
};
export default Login;
위의 코드에는 보이지 않지만, 라이브러리 사용전,provider로 감싸줘야 한다. 난 최상위인 main.tsx에 <GoogleOAuthProvider clientId={clientId}>
를 감싸줬다. 인자는 보다시피 client ID를 주면 된다.
scop에는 자신이 접근할 정보, onSuccess와 onError은 success/error 발생하면 실행할 함수를 기록한다.
flow: auth-code는 백엔드에서 refresh와 access token을 얻을 code를 얻기 위해 설정하였다
flow는 사용자 승인 작동 방식에 따라 갈리는데 자세한 것은 Authorization docs 를 읽어보자
받은 코드는 axios로 backend로 보내주자. post에 들어간 URI는 자신이 보낸 code를 처리할 api이다.
backend에서는 code를 token으로 교환하고, data로 던져준다.
onSuccess: async ({ code }) => {
axios
.post("http://localhost:4000/auth/google/callback", { code })
.then(({ data }) => {
console.log(data);
});
},
backend 처리도 살짝 살펴보자. google-auth-libray의 OAuth2Client를 client Id와 secret을 인자로 생성한다.
생선된 클라이언트에 code만 넣어주면, token 얻기 성공이다!
// front에서 넘어온 code를 정리합니다.
import {OAuth2Client} from "google-auth-library";
const oAuth2Client = new OAuth2Client(_google.clientId, _google.clientSecret, "postmessage");
fastify.post("/callback", async (req: FastifyRequest<{Body: {code: any}}>, res: FastifyReply) => {
const {tokens} = await oAuth2Client.getToken(req.body.code);
console.log("code ", tokens);
res.send(tokens);
});
}
🚨 OAuth2Client를 생성할 때, 3번 째 인자로 "postmessage"가 적혀 있을텐데, 절대 RedirectURI를 적으면 안된다.
google-auth-libray 최신 Docs를 보면, OAuth2Client로 redirect uri를 주는데, 그냥 postmessage로 두면 된다
Redirect uri를 주면, indirect uri 오류를 뱉는다. (docs를 좀 더 찾아봐야 할 듯)
여기까지 하면, token을 잘 받아오는 것을 확인 할 수 있다!
Error Report
idpiframe_initialization_failed
Error
브라우저의 캐시를 지워주자. 캐시를 지울 일이 개인적으로 구현하면서 많았는데, 정신 건강을 위해 시크릿 탭이나, PostMan을 사용하자
Origin is not allowed for the given client ID when using a GoogleLogin button
구글 클라우드 콘솔로 돌아가서, 리다이렉팅 URI과 승인된 자바스크립트 원본에 http://localhost
와 http://localhost:3000
을 적어주자
자신의 페이지가 열릴 URI와 포트를 적어주란 뜻이다!
느낀 점
- 어려운 문제일수록 stackoverflow나 다른 블로그를 보기 전에 docs를 읽는게 효과적이다
- 계속 라이브러리는 업데이트 되기 때문에, 잘못하면 에러의 늪에 빠진다
- BDD(블로그 주도 개발)이 내 성장에 크게 도움이 되지 않을 것이다
'DEV > Frontend' 카테고리의 다른 글
React state는 뭔가 (0) | 2023.02.08 |
---|---|
React Error Rendered more hooks than during the previous render (0) | 2023.02.08 |
리액트 에러 해결 Warning Each child in a list should have a unique key prop 에러 해결 (0) | 2023.01.13 |
React 왜 쓸까? (0) | 2023.01.12 |
Recoil 기초 (0) | 2023.01.12 |