uju's Tech

[Node.js] 소셜로그인 정복하기 - google 본문

Node

[Node.js] 소셜로그인 정복하기 - google

ujusy 2021. 5. 27. 17:40

<본 포스팅은 공부 목적으로 작성되었습니다. 혹시 틀린 부분이 있거나 문제가 되는 부분이 있다면 답글 달아주세요!>

 

소셜 로그인 개발은 몇달 전 진행했던 개발인데.. notion에 적어두었다가 지금에서야 블로그를 작성합니다 ㅎㅎ..

 

페이스북, 카카오, 애플, 구글 이렇게 4가지 소셜 로그인을 진행하였고 두 번째부터 정리해보겠다.

 

소셜 로그인 구현은 모두 공식문서를 기반으로 구현하였다.

 

문서를 읽어보면 소셜 회원가입 플로우는 모두 동일한 것 같다. 페이스북에서도 작성했지만 또 작성해보도록 하겠다.

 

 페이스북 회원가입 구현은 아래 링크로 ㅎㅎ

https://uju-tech.tistory.com/85

 

[Node.js] 소셜 로그인 정복하기 - facebook

<본 포스팅은 공부 목적으로 작성되었습니다. 혹시 틀린 부분이 있거나 문제가 되는 부분이 있다면 답글 달아주세요!> 소셜 로그인 개발은 몇달 전 진행했던 개발인데.. notion에 적어두었다가 지

uju-tech.tistory.com

 

1. 구글 회원가입 flow

 

문서를 읽어보면서 이해한 그대로 도식화해보았다.

 

<이해해본 순서>

1. client가 google server로 회원가입 요청

 

2. google server가 idToken 전송

 

3. client가 서비스 서버로 idToken 전송

 

4. 서비스 서버가 idToken이 유효한지 google server에 검증 및 유저 데이터 요청

 

5. 유효한 idToken이면 user Data 전송

 

6. 서비스 서버가 받은 유저 데이터를 저장 및 가공 후 client에 응답

 

2. 구글 소셜 검증 유틸리티 구현

 

공식 문서를 참고하여 구현하였다. 아래 링크를 통해 문서를 확인할 수 있다.

 

https://developers.google.com/identity/sign-in/web/backend-auth

 

백엔드 서버로 인증  |  Google Sign-In for Websites  |  Google Developers

백엔드 서버와 통신하는 앱 또는 사이트에서 Google 로그인을 사용하는 경우 서버에서 현재 로그인 한 사용자를 식별해야 할 수 있습니다. 보안을 유지하려면 사용자가 성공적으로 로그인 한 후 H

developers.google.com

문서를 보면 Node.js 예시를 확인할 수 있는데 그대로 따라 구현해주면 된다. 

 

아래 코드는 공식 문서의 예시 코드이다.

const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client(CLIENT_ID);
async function verify() {
  const ticket = await client.verifyIdToken({
      idToken: token,
      audience: CLIENT_ID,  // Specify the CLIENT_ID of the app that accesses the backend
      // Or, if multiple clients access the backend:
      //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
  });
  const payload = ticket.getPayload();
  const userid = payload['sub'];
  // If request specified a G Suite domain:
  // const domain = payload['hd'];
}
verify().catch(console.error);

주의해야되는 부분은 audience의 CLIENT_ID이다.

 

설명을 보면 백엔드에 접속할 app의 client id라고 되어있는데 

위 코드의 const client = new OAuth2Client(CLIENT_ID); 부분의 client id와 항상 동일한 것이 아니다.

 

동일하게 사용하려면 프론트에서도 백엔드에 설정된 client id를 사용해주어야 한다. 그게 아니라면 프런트에서 사용하는 client id를 지정해주도록 하자..

 

그렇게 안 하면 

Error: Wrong recipient, payload audience != requiredAudience
   at OAuth2Client.verifySignedJwtWithCertsAsync

 에러가 발생하니 주의하자..ㅜㅜ

 

++ const client = new OAuth2Client(CLIENT_ID);에서 사용되는 클라이언트 ID는 gcp의 'api 및 서비스' 의 '사용자 인증 정보 ' 에서 발급 받아 사용하면 된다

 

 

필자는 아래와 같이 검증 유틸리티를 작성해주었다.

 

const env = process.env.NODE_ENV || 'local';

const { OAuth2Client } = require('google-auth-library');

let googleAccountOauthClient;
if (env !== 'ci') {
  if (!process.env.SECRETS) {
    throw Error('`SECRETS` 환경변수가 설정되어 있지 않습니다');
  }
  googleAccountOauthClient = JSON.parse(process.env.SECRETS).oauth.google;

  if (!googleAccountOauthClient.clientId) {
    throw Error('`SECRETS`에 `clientId`가 없습니다.');
  }
}

/**
 * @param {string} token
 * @returns {Promise<TokenPayload|undefined|true>}
 * @throws Error
 */
const verifyGoogle = (() => {
  if (env === 'ci') return async () => true;

  const client = new OAuth2Client(googleAccountOauthClient.clientId);

  return async (token) => {
    const ticket = await client.verifyIdToken({
      idToken: token,
      audience: googleAccountOauthClient.clientId,
    });
    return ticket.getPayload();
  };
})();

module.exports = {
  verifyGoogle,
};

 

개인적으로 구글이 문서화가 잘되어있어서 개발하기 아주 편했다~~ ㅎㅎ

 

예시 코드도 잘되어있어 이해하는데 무리가 없었고 빠르게 뚝딱 만들어보았다 ㅎ! 

 

다음 포스팅 iOS에서 소셜 로그인을 사용하려면 필수로 애플 로그인을 넣어야 하기 때문에 애플 소셜 회원가입 구현에 대해 알아보겠다 뿅!

Comments