κ΅¬κΈ API λ±λ‘ λ§ν¬ μ μ ν, νλ‘μ νΈ μμ±
κ·Έ νμ API λ° μλΉμ€λ‘ μ΄λ ν, OAuth λμ νλ©΄ μ ν!
νλ‘μ νΈ μ΄λ¦ μμ μμΉν, μ± μμ
λ²νΌ ν΄λ¦
λ²μ μΆκ° λλ μμ
λ²νΌμ ν΄λ¦ν΄μ νμν μ 보λ₯Ό λΆλ¬μ€κΈ° μν΄ λ²μ μ€μ (!!μ€μν λΆλΆ!!)
νμ΄μ§ νλ¨μ μ μ₯ ν κ³μ
λ²νΌ ν΄λ¦ ν, λ§μ§λ§ νμ΄μ§μμ λμ보λλ‘ λμκ°κΈ°
λ²νΌ ν΄λ¦νλ©΄ OAuth λμ νλ©΄ μ€μ μλ£ π
κ·Έλ¬λ©΄ μ΄μ μ¬μ©μ μΈμ¦ μ 보 μ€μ νλ¬ κ³ κ³ !
μ¬μ©μ μΈμ¦ μ 보 λ§λ€κΈ°
λ²νΌ ν΄λ¦ν, OAuth ν΄λΌμ΄μΈνΈ ID ν΄λ¦
μ ν리μΌμ΄μ μ νμ μΉ μ ν리μΌμ΄μ μ ν! (νλ‘μ νΈ μ νμ λ§κ² μ ννλ©΄ λ λ―)
μΉμΈλ 리λλ μ
URIλ μ°λ¦¬ νλ‘μ νΈμ apiμ λ§κ²λ μ£Όμ μ€μ
λμ€μ λ°°ν¬νκ² λλ©΄, μ΄ κ³³μ λ°°ν¬λ§ν¬ μΆκ°ν΄μ€μΌ λ°°ν¬ νμλ κ΅¬κΈ μμ
λ‘κ·ΈμΈ μ¬μ©μ΄ κ°λ₯
λ§λ€κΈ°
λ²νΌμ ν΄λ¦νλ©΄, ν΄λΌμ΄μΈνΈ IDμ ν΄λΌμ΄μΈνΈ 보μ λΉλ°λ²νΈκ° λ°κΈλλλ° μ 보κ΄ν΄λκ³ , μ μΆλμ§ μκ² μ‘°μ¬!!
κ·Έλ¦¬κ³ ν΄λΌμ΄μΈνΈ IDλ .env νμΌμ΄λ λ³λμ νμΌμ μ 볡λΆν΄λκΈ°
ννμ΄μ§μμ κ΅¬κΈ λ‘κ·ΈμΈ
λ²νΌμ λλ₯΄λ©΄, μλ μ½λκ° μ€νλ¨
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;
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);
}
},
};