[TIL] 2020. 09. 03. Vue.js에서_SDK를_이용해서_refresh_token_받아보기

달밤·2020년 9월 3일
0

TIL

목록 보기
105/110
post-thumbnail

오늘 배운 것

Vue.js에서 Google SDK를 이용해서 Refresh Token 받기

//index.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>

<body>
  <div id="app"></div>
  //구글에서 제공하는 자바스크립트용 sdk를 사용하기 위해서 script를 불러온다.
  <script src="https://apis.google.com/js/platform.js"></script>
</body>

</html>
//Login.vue
<template>
  <div>
    <div>로그인 페이지입니다.</div>
    //버튼을 클릭하면 googleSocialLogin 함수 실행
    <button @click="googleSocialLogin">구글 소셜 로그인</button>
  </div>
</template>

<script>
import axios from "axios";
import qs from "qs";

export default {
  data() {
    return {};
  },
  methods: {
    //sdk
    googleSocialLogin() {
      //auth2 로드
      let vm = this;
      window.gapi.load("auth2", function() {
        //GoogleAuth객체 생성
        let gauth = window.gapi.auth2.init({
          client_id: process.env.VUE_APP_GOOGLE_CLIENT_ID,
          scope: "openid email profile"
        });
        gauth.then(
          //GoogleAuth 초기화 성공
          response => {
            if (gauth.isSignedIn.get()) {
              //만약 로그인이 이미 되어있다면,
              //액세스 토큰 반환
              console.log(response.Pd.aC);
              //액세스 토큰을 서버로 전송 및 응답에 따라 라우팅(구현 예정)
              vm.$router.push("/edit");
            }
            //로그인이 되어 있지않으면
            //오프라인 액세스 권한요청
            else {
              gauth.grantOfflineAccess().then(
                //로그인 성공
                response => {
                  console.log(response.code);
                  //getGoogleRefreshToken 함수를 호출
                  vm.getGoogleRefreshToken(response.code);
                },
                //로그인 실패
                err => {
                  console.log(err);
                }
              );
            }
          },
          //GoogleAuth 초기화 실패
          error => {
            console.log(error);
          }
        );
      });
    },
    getGoogleRefreshToken(code) {
      //받은 코드를 바탕으로 access_token 및 refresh_token 요청
      if (code) {
        const url = "https://oauth2.googleapis.com/token";
        const query = qs.stringify({
          code: code,
          client_id: process.env.VUE_APP_GOOGLE_CLIENT_ID,
          client_secret: process.env.VUE_APP_GOOGLE_CLIENT_SECRET,
          redirect_uri: "postmessage",
          grant_type: "authorization_code"
        });

        axios
          .post(url, query)
          //psot요청이 성공했을 시
          .then(res => {
            //서버로 access_token 및 refresh_token 전달(구현 예정)
            console.log(res);
            //서버응답에 따라서 editpage 혹은 signup로 이동(구현 예정)
            this.$router.push("/edit");
          })
          //post요청이 실패했을 시
          .catch(err => {
            //에러 메시지를 띄우기
            console.log(err);
          });
      }
    }
  }
};
</script>

특이점

  • https://developers.google.com/identity/sign-in/web/reference에서 구글 gapi 메소드들을 정독하고 시작한다.
  • 자바스크립트 SDK를 이용해서 구글 로그인을 진행할 시에 refresh 토큰을 받을 수 없다. 구글에서 권장하는 방식은 클라이언트 단에서 SDK를 이용해서 "authorization_code"를 받은 다음, 이 코드를 서버로 넘겨서 서버에서 refresh 토큰을 얻게 끔 하는 방식을 권장하고 있다.
  • 어쩔 수 없이 gauth.grantOfflineAccess() 통해서 "authorization_code"를 받아내고 다시 구글의 /token 엔드포인트로 post요청을 보내서 "access_token"과 "refresh_token"을 받고 있다.
  • 결국엔 반쪽짜리 SDK다. SDK + HTTP요청이 반반이니.
  • 나는 클라이언트 단에서 "refresh_token"이 필요했기 때문에 이런식으로 어거지로 구현했다. 만약 access_token과 유저정보만 필요한 경우라면 SDK만으로도 구현이 가능하다.
  • 이런식으로 구현 할 경우 network 탭에서 요청 header를 살펴보면 client_secret이 그대로 명시되어 있다는 점을 알 수 있다. 보안적으로 취약할 수 밖에 없는 방식이다.(한계점)
  • "getGoogleRefreshToken" 함수에서 post요청을 보낼 때 "redirect_uri"에 클라이언트 ID만들 때 적은 "redirect_uri" 적으면 "redirect_uri mismatch" 오류가 뜬다. 그래서 "postmessage"로 바꾸니 정상적으로 요청이 되었다.
  • GoogleAuth 프로미스 내에서는 "this"가 vue 인스턴스가 아니다. 메소드 바깥에서 this를 다른 변수에 할당을 해서 사용해야 한다.
  • HTTP 요청으로만 구현한 것보다 코드는 좀 더 깔끔한 것 같다. HTTP 요청시 code를 달고 redirect 되는데 그 때 달린 쿼리들이 꽤 더럽고, created()같은 라이프사이클 메소드로 받아와야하기 때문에 좀 별로다.
profile
다 늦은 밤, 달밤의 개발일기

0개의 댓글