본격적으로 OAuth 구현을 위해 여러 소셜로그인 구현에 관련된 글들은 다 읽어본 듯 하다.
하지만 무언가 다 2%씩 부족한 느낌이었고, 이제부터 구현을 시작 할 사람들을 위해 조금 더 자세하게 적어보려고 포스팅을 한다!
구현 전에 OAuth의 흐름을 알고 구현을 하는 것이 중요하므로 이전 포스팅을 꼭 꼭 읽어 흐름을 익힌 뒤 구현을 시작하도록 하자.
우선 모든 소셜 로그인 구현의 지름길은 공식문서를 정독하는 일이다.
구글 oAuth 공식 문서와 클라이언트 측 웹 애플리케이션용 OAuth 2.0 에 하고자 하는 내용이 다 나와있다.
소셜로그인을 구현하기 위해서는 구글 cloud에 애플리케이션 등록이 필요하다. 애플리케이션을 등록하면서 해당 애플리케이션의 이름, 필요로 하는 api, redirect uri 등의 정보들을 제공해주어야 로그인 구현이 가능하므로 먼저 애플리케이션 등록부터 하자.
애플리케이션에 관해서는 [React.js] 리액트js 구글 로그인 구현하기 블로그와 [자바스크립트] 구글 로그인 API 쉽게 구현 방법 및 예제- OAuth 2.0, Javascript, Jsp 블로그에 포스팅이 잘 되어있다.
구글은 다른 소셜로그인들과 다르게 react-google-login 라이브러리가 아주아주 잘 되어있어서 구현이 매우 쉬웠다.
참고로 다른 로그인은 OAuth의 흐름대로 인가코드를 클라이언트 단에서 발급받고 서버로 넘겨준 뒤 서버에서 access_token을 발급 받지만 해당 라이브러리는 클라이언트 단에서 다이렉트로 access_token까지 발급받을 수 있다. 라이브러리를 사용하지않고 직접 구현한다면 OAuth의 흐름을 참고해서 구현하자.
yarn add react-google-login
npm install react-google-login
구현하고자 하는 프로젝트에 해당 라이브러리를 설치해준다. yarn 사용자는 위의 명령어, npm 사용자는 아래의 명령어를 실행하면 설치가 완료된다.
만약 프로젝트에 client와 server가 같이 있다면 client 디렉토리 안에서 설치해주자.
import React from "react";
import GoogleLogin from "react-google-login";
import { gapi } from "gapi-script";
import axios from "axios";
const LoginPage = () => {
const onGoogleSuccess = async (res) => {
let body = {
access_token: res.accessToken,
id_token: res.tokenId,
};
await axios
.post(`${해당 프로젝트의 서버 도메인}/accounts/rest-auth/google/`, body, {
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
console.log(response);
localStorage.setItem("accessToken", response.data.access_token);
navigate("/");
})
.catch((error) => console.log(error));
};
// google login Failure
const onGoogleFailure = (res) => {
window.alert("구글 로그인에 실패하였습니다.");
console.log("error", res);
};
gapi.load("client:auth2", () => {
gapi.client.init({
clientId: `${발급받은 구글 클라이언트 아이디}.apps.googleusercontent.com`,
plugin_name: "chat",
});
});
return (
<div>
<GoogleLogin
clientId={발급받은 구글 클라이언트 아이디}
onSuccess={onGoogleSuccess}
onFailure={onGoogleFailure}
buttonText=""
render={(renderProps) => (
<button onClick={renderProps.onClick}>
<FontAwesomeIcon icon={faGoogle} color="white" />
</button>
)}
/>
</div>
)
}
export default LoginPage;
우선은 구글 react-google-login 라이브러리를 사용하기 위해 import 해주자.
gooleLogin 컴포넌트를 return에 넣어주면 구글 로그인 버튼이 간단하게 구현되어있다. 나는 기본 디자인이 마음에 들지 않아 커스텀하기 위해 render를 쓰고 내부에서 FontAwesomeIcon을 가져와 커스텀했지만 구글에서 제공하는 기본 디자인을 사용하고 싶은 사람은 render 부분을 빼주자.
내부의 onSuccess은 구글 로그인이 성공했을 때 실행 될 함수를 정의할 수 있고, onFailure은 구글 로그인이 실패했을 때 실행 될 함수를 정의할 수 있다.
onSuccess와 onFailure 안의 함수는 똑같이 할 필요 없이 본인 프로젝트에 맞는 방식으로 구현하면 된다. 나는 성공하면 access token을 서버로 넘겨주고 response받은 access token을 localStorage에 저장하도록 구현했다.
내부의 clientId에는 본인이 발급받은 애플리케이션의 클라이언트 아이디를 넣어주어야한다.
여기서 주의해야하는 점은 gapi와 관련된 코드인데 요것을 작성하지 않았을 때 정말 다양한 에러가 났다..
react-google-login 공식 문서에 왜 에러가 나는지 적혀있다.
idpiframe_initialization_failed
err = {error: "popup_closed_by_user"}
요 두개의 에러가 가장 많이 났다.
참고로 나는 두가지 에러 전부 위의 방법으로 해결이 안되어서 gapi 와 관련한 코드를 작성해주니 해결되었다. 같은 에러가 뜬다면 위의 해결 방법을 시도해보고 안된다면 위에 구현해둔 gapi 관련 코드를 작성해보자.🥲