안녕하세요 프론트엔드 개발자 ken입니다. 오늘은 구글 로그인 동작 방식과 간단한 예제 코드에 대해 알아보겠습니다.
구글 로그인은 기본 방식인 권한 부여 승인 코드 방식을 채택하고 있습니다.
Google Developers 설정
1. https://console.cloud.google.com 접속
2. API 및 서비스 -> 사용자 인증 정보 -> OAuth 2.0 클라이언트 ID에서 id 생성
필수 정보 입력
- 애플레이케이션 유형 항목에 '웹 애플리케이션' 선택
- 애플리케이션 이름 입력
- 승인된 자바스크립트 원본 항목에 구글 로그인을 사용할 홈페이지 주소 입력
- 승인된 리디렉션 URI 항목에 구글 로그인 후 Redirect할 주소 입력
로컬에서 테스트가 필요하므로 https://localhost:3000을 추가해주세요
해당 과정이 완료되면 아래와 같이 클라이언트 ID를 발급받습니다.
구현 방법
프론트에서는 아래와 같이 구현하였습니다.
저는 react-oauth/google 라이브러리를 이용하였는데요 해당 라이브러리는 복잡한 구글 로그인을 단 몇줄의 코드로 구현하여 가독성이 좋은 장점이 있습니다.
먼저 라이브러리에서 지원하는 GoogleOAuthProvider로 코드를 감싸고 구글에서 발급받은 clientId를 인자로 넘겨줍니다.
<GoogleOAuthProvider clientId={clientId}>
<GoogleLoginButton />
</GoogleOAuthProvider>
useGoogleLogin에서는 로그인 성공시 토큰을 정상적으로 발급해줍니다.
const handleLogin = useGoogleLogin({
onSuccess: async (res) => {
// 구글 로그인 성공시 해당 토큰을 백엔드 서버로 전송
await signInSocial({type: 'google', token: res.access_token, platform: 'web'})
},
onError: () => {
...
}
})
동작 방식
구글 로그인의 동작방식은 다음과 같습니다
1. 사용자가 로그인을 시도하면 구글 인증 서버로 oauth2.0 요청을 보내고 code값 또는 access_token값을 받습니다.
2. 반환받은 토큰값과 설정에서 진행한 client_id, client_secrect, redirect_uri을 넣고 추가로 grant_type을 함께 넣어 구글 토큰 서버로 요청을 보냅니다.
3. 인증이 완료되면 서버에서는 access_token을 반환해주고 해당 토큰값을 통해 API를 사용할 수 있는 자격을 가집니다.
개발 기록
저는 구글 로그인을 oauth2.0을 이용하여 구현하였습니다. 설정이 완료되고 react-oauth/google 라이브러리를 이용하여 로그인을 구현하였습니다.
구글 로그인 버튼이 기본으로 설정되어있기 때문에 커스텀을 시도하였습니다.
커스텀 시도
로그인 버튼을 커스텀 하기 위해 라이브러리에서 제공되는 useGoogleLogin을 사용하였습니다.
사용법은 아래를 참고해주세요
로그인 프로세스를 사용자가 로그인을 시도하면 구글에서 access_token을 반환해주고 해당 값을 서버로 전송하면 서버에서 검증하여 로그인 토큰을 내려주는 방식으로 설계하여 구현하였습니다.
하지만 프론트에서는 oauth2.0 방식을 사용하여 토큰을 전송했지만 서버에서는 oauth1.0방식으로 구현되어 있어 토큰값이 맞지 않아 오류가 발생했습니다.
저는 서버와 맞추기 위해 oauth1.0방식으로 구현할 수 있는 GoogleLogin을 사용했습니다. 커스텀을 하려면 직접 클래스명을 찾아 css를 조작해야 했습니다. 버튼은 iframe으로 제작되어 있었는데 내부 css를 조작하는것이 불가능 했고 회사 프로젝트에서 사용하는 css 라이브러리가 styled components를 사용하기 때문에 GoogleLogin 커스텀이 어려웠습니다.
tailwind로 커스텀이 가능하지만 해당 버튼 커스텀을 위해 나머지 스타일 코드를 전부 tailwind로 수정하는것은 너무 비효율적이라고 생각하여 커스텀이 가능한 useGoogleLogin을 사용하기로 결정했습니다.
커스텀을 위해 useGoogleLogin을 사용해야 하므로 api 수정이 필요하였습니다. 저는 백엔드 개발자분께 제가 시도한 방법을 말씀드리고 api 수정이 필요하다고 판단하여 요청을 하였습니다.
구현 방법
const googleLogin = useGoogleLogin({
onSuccess: async ({ code }) => {
const tokens = await axios.post('https://oauth2.googleapis.com/token', {
code,
client_id,
client_secret,
redirect_uri,
grant_type
});
await signInSocial({type: 'google', token: tokens.access_token, platform: 'web'})
},
flow: 'auth-code',
});
프론트에서는 위와 같이 구현하였습니다.
사용자가 로그인을 시도하여 성공하면 code값을 받습니다.
해당 code값을 https://oauth2.googleapis.com/token 주소로 보내면 google의 access_token을 반환해주고 해당 토큰을 서버로 보내면 login에 대한 access_token과 refresh_token을 받습니다.
하지만 프론트에서 토큰을 받고 다시 서버로 보내는 방식이 안전하지 않다고 판단하여 백엔드 개발자분과 협의 후 백엔드에서 해당 과정을 진행하기로 수정했습니다.
const handleLogin = useGoogleLogin({
onSuccess: async (res) => {
await signInSocial({type: 'google', token: res.access_token, platform: 'web'})
},
onError: () => {
...
}
})
프론트에서는 access_token만 보내고 나머지 토큰 교환 과정은 백엔드에서 진행됩니다.
'OAUTH' 카테고리의 다른 글
Apple 로그인 구현해보기 (0) | 2023.12.18 |
---|---|
카카오 로그인 구현해보기 (2) | 2023.12.18 |
소셜 로그인의 동작원리는 무엇일까? (0) | 2023.10.16 |