[Week2] Google Login

tiaΒ·2022λ…„ 2μ›” 17일
1

νŒŒμ΄λ„ν”„λ‘œμ νŠΈ

λͺ©λ‘ 보기
4/9

πŸ‘» Google Login

1. ꡬ글 API 등둝

ꡬ글 API 등둝 링크 접속 ν›„, ν”„λ‘œμ νŠΈ 생성
κ·Έ 후에 API 및 μ„œλΉ„μŠ€λ‘œ 이동 ν›„, OAuth λ™μ˜ ν™”λ©΄ 선택!
ν”„λ‘œμ νŠΈ 이름 μ˜†μ— μœ„μΉ˜ν•œ, μ•± μˆ˜μ • λ²„νŠΌ 클릭

λ²”μœ„ μΆ”κ°€ λ˜λŠ” μ‚­μ œ λ²„νŠΌμ„ ν΄λ¦­ν•΄μ„œ ν•„μš”ν•œ 정보λ₯Ό 뢈러였기 μœ„ν•΄ λ²”μœ„ μ„€μ •(!!μ€‘μš”ν•œ λΆ€λΆ„!!)

νŽ˜μ΄μ§€ ν•˜λ‹¨μ˜ μ €μž₯ ν›„ 계속 λ²„νŠΌ 클릭 ν›„, λ§ˆμ§€λ§‰ νŽ˜μ΄μ§€μ—μ„œ λŒ€μ‹œλ³΄λ“œλ‘œ λŒμ•„κ°€κΈ° λ²„νŠΌ ν΄λ¦­ν•˜λ©΄ OAuth λ™μ˜ ν™”λ©΄ μ„€μ • μ™„λ£Œ πŸ™‚

그러면 이제 μ‚¬μš©μž 인증 정보 μ„€μ •ν•˜λŸ¬ κ³ κ³ !

μ‚¬μš©μž 인증 정보 λ§Œλ“€κΈ° λ²„νŠΌ 클릭후, OAuth ν΄λΌμ΄μ–ΈνŠΈ ID 클릭

μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μœ ν˜•μ€ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 선택! (ν”„λ‘œμ νŠΈ μœ ν˜•μ— 맞게 μ„ νƒν•˜λ©΄ 될 λ“―)

승인된 λ¦¬λ””λ ‰μ…˜ URIλŠ” 우리 ν”„λ‘œμ νŠΈμ˜ api에 λ§žκ²Œλ” μ£Όμ†Œ μ„€μ •
λ‚˜μ€‘μ— λ°°ν¬ν•˜κ²Œ 되면, 이 곳에 배포링크 μΆ”κ°€ν•΄μ€˜μ•Ό 배포 후에도 ꡬ글 μ†Œμ…œ 둜그인 μ‚¬μš©μ΄ κ°€λŠ₯

λ§Œλ“€κΈ° λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄, ν΄λΌμ΄μ–ΈνŠΈ ID와 ν΄λΌμ΄μ–ΈνŠΈ λ³΄μ•ˆ λΉ„λ°€λ²ˆν˜Έκ°€ λ°œκΈ‰λ˜λŠ”λ° 잘 보관해두고, μœ μΆœλ˜μ§€ μ•Šκ²Œ 쑰심!!

그리고 ν΄λΌμ΄μ–ΈνŠΈ IDλŠ” .env νŒŒμΌμ΄λ‚˜ λ³„λ„μ˜ νŒŒμΌμ— 잘 볡뢙해놓기

2. client μ„€μ •

ν™ˆνŽ˜μ΄μ§€μ—μ„œ ꡬ글 둜그인 λ²„νŠΌμ„ λˆ„λ₯΄λ©΄, μ•„λž˜ μ½”λ“œκ°€ 싀행됨

Reactμ—μ„œ .env ν™˜κ²½ λ³€μˆ˜ μ„€μ •μ‹œ,
ν™˜κ²½ λ³€μˆ˜ μ•žμ— κΌ­ REACT_APP λΆ™μ—¬μ€˜μ•Όν•¨!!!

const handleGoogle = () => {
	const GOOGLE_LOGIN_URL = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.REACT_APP_GOOGLE_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_GOOGLE_REDIRECT_URI}&response_type=code&scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile`;
    window.location.assign(GOOGLE_LOGIN_URL);
  };

우리 ν”„λ‘œμ νŠΈμ—μ„œλŠ” ꡬ글 λ‘œκ·ΈμΈμ‹œ, ꡬ글 이메일 정보와 ꡬ글 λ‹‰λ„€μž„ 정보가 ν•„μš”ν–ˆκΈ°μ—
μ•„λž˜ μ£Όμ†Œμ—μ„œ scope μ„€μ •μ‹œ 2개의 정보λ₯Ό μš”μ²­ν•΄μ•Ό ν–ˆμŒ

scope λΆ€λΆ„λ§Œ λ³„λ„λ‘œ 기둝을 ν•΄λ³΄μžλ©΄,
1개 μ΄μƒμ˜ scope이 ν•„μš”ν• μ‹œμ—λŠ” api μ£Όμ†Œ 사이에 띄어쓰기λ₯Ό ν•΄μ£Όλ©΄ 잘 μž‘λ™ν•¨
(이거 μ™„μ „ κΏ€νŒ!)

scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile`;

그리고 μ‚¬μš©ν•  수 μžˆλŠ” scope 섀정은 μœ„μ˜ API μ„€μ •μ—μ„œ
λ²”μœ„ μΆ”κ°€ λ˜λŠ” μ‚­μ œλ₯Ό 톡해 λ²”μœ„λ₯Ό μΆ”κ°€ν•΄μ€˜μ•Ό μΆ”κ°€ν•΄μ€€ λ²”μœ„μ— ν•œν•΄μ„œ scope 섀정이 κ°€λŠ₯ 😎

Router.js νŒŒμΌμ— μ•„λž˜μ™€ 같이 라우트 μΆ”κ°€

<Route path="/google/signin" element={<Google />} />

Google.js 파일 섀정은 μ•„λž˜μ™€ 같이 😎

import { useState, useEffect } from 'react';
import axios from 'axios';
import { useDispatch } from 'react-redux';
import { socialSignIn, setSocialUser } from '../../redux/user/userSlice';
import { useNavigate } from 'react-router-dom';

const Google = () => {
  const dispatch = useDispatch();
  const navigate = useNavigate();
  const [token, setToken] = useState();

  const getGoogleCode = () => {
    const googleCode = new URL(window.location.href).searchParams.get('code');
    if (googleCode) {
      getToken(googleCode);
    }
  };

  const getToken = async (code) => {
    try {
      const data = await axios.post('/google/signin', {
        code,
      });
      setToken(data.data.access_token);
    } catch (e) {
      console.log(e);
    }
  };

  const getUserInfo = async (token) => {
    try {
      const data = await axios.get(`/google/user?accessToken=${token}`);
      if (data) {
        const { email, name, user_type: who } = data.data.giverInfo;
        dispatch(socialSignIn());
        dispatch(setSocialUser({ email, name, who }));
        localStorage.setItem('token', token);
        navigate('/');
      }
    } catch (e) {
      console.log(e);
    }
  };

  useEffect(() => getGoogleCode(), []);

  useEffect(() => getUserInfo(token), [token]);

  return (
    <>
      <div></div>
    </>
  );
};

export default Google;

3. server μ„€μ •

router νŒŒμΌμ— μ•„λž˜ λ‚΄μš© μΆ”κ°€

router.post('/google/signin', user.googleLogin.getToken);
router.get('/google/user?', user.googleLogin.getUser);

googleLogin.js 파일 섀정은 μ•„λž˜μ™€ 같이 😎

'use strict';
const axios = require('axios');
const jwt = require('jsonwebtoken');
const { giver } = require('../../models');

module.exports = {
  getToken: async (req, res) => {
    const code = req.body.code;
    const url = `https://oauth2.googleapis.com/token?code=${code}&client_id=${process.env.GOOGLE_CLIENT_ID}&client_secret=${process.env.GOOGLE_CLIENT_SECRET}&redirect_uri=${process.env.GOOGLE_REDIRECT_URI}&grant_type=${process.env.GOOGLE_GRANT_TYPE}`;
    try {
      const token = await axios.post(url, {
        headers: { 'content-type': 'application/x-www-form-urlencoded' },
      });
      const data = token.data;
      res.send(data);
    } catch (e) {
      console.log(e);
    }
  },
  getUser: async (req, res) => {
    const token = req.query.accessToken;
    const googleAPI = `https://www.googleapis.com/oauth2/v2/userinfo?access_token=${token}`;
    try {
      const googleUser = await axios.get(googleAPI, {
        headers: {
          authorization: `Bearer ${token}`,
        },
      });
      const user = googleUser.data;

      const giverFound = await giver.findOne({ where: { email: user.email } });

      if (giverFound) {
        const giverInfo = giverFound.dataValues;
        delete giverInfo.password;
        const accessToken = jwt.sign(giverInfo, process.env.ACCESS_SECRET);
        res.send({ accessToken, giverInfo });
      } else {
        const newGiver = await giver.create({
          email: user.email,
          name: user.name === '' ? '' : user.name,
          user_type: 1,
        });
        const { id, email, name, user_type } = newGiver.dataValues;
        const giverInfo = { id, email, name, user_type };
        const accessToken = jwt.sign(giverInfo, process.env.ACCESS_SECRET);
        res.send({ accessToken, giverInfo });
      }
    } catch (e) {
      console.log(e);
    }
  },
};

0개의 λŒ“κΈ€