diff --git a/package.json b/package.json index 7f46d344..9429b6ef 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@types/react-dom": "^18.0.0", "axios": "^0.27.2", "jotai": "^1.11.0", + "qs": "^6.11.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.36.1", @@ -69,5 +70,6 @@ "stylelint": "^14.9.1", "stylelint-config-standard": "^26.0.0", "stylelint-config-standard-scss": "^4.0.0" - } + }, + "proxy": "https://nid.naver.com" } diff --git a/src/App.tsx b/src/App.tsx index bbce53e9..484ce982 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,6 +20,9 @@ import Withdrawal from 'pages/Setting/Withdrawal'; import Inquiry from 'pages/Inquiry'; import Myinquiry from 'pages/Inquiry/Myinquiry'; import Notice from 'pages/Notice'; +import KakaoLogin from 'pages/Auth/OAuth/KakaoLogin'; +import NaverLogin from 'pages/Auth/OAuth/NaverLogin'; +import GoogleLogin from 'pages/Auth/OAuth/GoogleLogin'; export default function App(): JSX.Element { return ( @@ -50,6 +53,9 @@ export default function App(): JSX.Element { } /> } /> } /> + } /> + } /> + } /> diff --git a/src/config/constants.ts b/src/config/constants.ts index 055db90a..eb03ad73 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -25,4 +25,4 @@ export const KAKAO_REDIRECT_URL = `https://kauth.kakao.com/oauth/authorize?clien // 네이버 OAuth export const NAVER_CLIENT_ID = checkEnvVar('REACT_APP_NAVER_CLIENT_ID'); -export const NAVER_REDIRECT_URL = `https://nid.naver.com/oauth2.0/authorize?client_id=${NAVER_CLIENT_ID}&redirect_uri=${SERVER_LOGIN_REDIRECT_URL}/naver&response_type=code`; +export const NAVER_REDIRECT_URL = `https://nid.naver.com/oauth2.0/authorize?client_id=${NAVER_CLIENT_ID}&redirect_uri=${SERVER_LOGIN_REDIRECT_URL}/naver&response_type=code&state=1`; diff --git a/src/pages/Auth/OAuth/GoogleLogin.tsx b/src/pages/Auth/OAuth/GoogleLogin.tsx new file mode 100644 index 00000000..7f3e52f2 --- /dev/null +++ b/src/pages/Auth/OAuth/GoogleLogin.tsx @@ -0,0 +1,44 @@ +import axios from 'axios'; +import { API_PATH } from 'config/constants'; +import { useEffect } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { useUpdateAuth } from 'store/auth'; + +export default function GoogleLogin() { + const location = useLocation(); + const updateAuth = useUpdateAuth(); + const navigate = useNavigate(); + const snsLogin = async () => { + try { + const code = location.search.slice(6, location.search.length).split('&')[0]; + const clientId = process.env.REACT_APP_GOOGLE_CLIENT_ID; + const clientSecret = process.env.REACT_APP_GOOGLE_CLIENT_SECRET; + const redirectUri = process.env.REACT_APP_SERVER_LOGIN_REDIRECT_URL; + const requestBody = `code=${code}&client_id=${clientId}&client_secret=${clientSecret}&redirect_uri=${redirectUri}/google&grant_type=authorization_code`; + + const googleResponse = await axios.post('https://oauth2.googleapis.com/token', requestBody); + const googleIdToken = googleResponse.data.id_token; + const googleLogin = await axios.post(`${API_PATH}/login/GOOGLE`, {}, { + headers: { + Authorization: googleIdToken, + }, + }); + sessionStorage.setItem('accessToken', googleLogin.data.accessToken); + localStorage.setItem('refreshToken', googleLogin.data.refreshToken); + updateAuth(); + } catch (e) { + // console.log(e); + } + }; + useEffect(() => { + if (location !== undefined) { + snsLogin(); + } else { + // url 오류로 인한 콜백 + navigate('/login'); + } + }); + return ( +
+ ); +} diff --git a/src/pages/Auth/OAuth/KakaoLogin.tsx b/src/pages/Auth/OAuth/KakaoLogin.tsx new file mode 100644 index 00000000..49059090 --- /dev/null +++ b/src/pages/Auth/OAuth/KakaoLogin.tsx @@ -0,0 +1,57 @@ +import { useLocation, useNavigate } from 'react-router-dom'; +import { useEffect } from 'react'; +import { API_PATH } from 'config/constants'; +import axios, { AxiosResponse } from 'axios'; +import qs from 'qs'; +import { useUpdateAuth } from 'store/auth'; + +interface KakaoResponse { + access_token: string, + expires_in: number, + refresh_token: string, + refresh_token_expires_in: number, + scope: string, + token_type: string, +} + +export default function KakaoLogin() { + const location = useLocation(); + const updateAuth = useUpdateAuth(); + const navigate = useNavigate(); + const headers = { + 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', + }; + const data = { + grant_type: 'authorization_code', + client_id: process.env.REACT_APP_KAKAO_CLIENT_ID, + redirect_uri: `${process.env.REACT_APP_SERVER_LOGIN_REDIRECT_URL}/kakao`, + code: location.search.slice(6, location.search.length), + }; + const snsLogin = async () => { + try { + const response: AxiosResponse = await axios.post('https://kauth.kakao.com/oauth/token', qs.stringify(data), { headers }); + const kakaoAccessToken = response.data.access_token; + + const kakaoLogin = await axios.post(`${API_PATH}/login/KAKAO`, {}, { + headers: { + Authorization: kakaoAccessToken, + }, + }); + sessionStorage.setItem('accessToken', kakaoLogin.data.accessToken); + localStorage.setItem('refreshToken', kakaoLogin.data.refreshToken); + await updateAuth(); + } catch { + // + } + }; + useEffect(() => { + if (location !== undefined) { + snsLogin(); + } else { + navigate('/login'); + } + }); + return ( +
+ ); +} diff --git a/src/pages/Auth/OAuth/NaverLogin.tsx b/src/pages/Auth/OAuth/NaverLogin.tsx new file mode 100644 index 00000000..b58e5985 --- /dev/null +++ b/src/pages/Auth/OAuth/NaverLogin.tsx @@ -0,0 +1,40 @@ +import axios from 'axios'; +import { API_PATH } from 'config/constants'; +import { useEffect } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { useUpdateAuth } from 'store/auth'; + +export default function NaverLogin() { + const location = useLocation(); + const updateAuth = useUpdateAuth(); + const navigate = useNavigate(); + const clientId = process.env.REACT_APP_NAVER_CLIENT_ID; + const clientSecret = process.env.REACT_APP_NAVER_CLIENT_SECRET; + const snsLogin = async () => { + try { + const naverResponse = await axios.post(`/oauth2.0/token?grant_type=authorization_code&client_secret=${clientSecret}&client_id=${clientId}&code=${location.search.split('&')[0].slice(6)}&state=1`); + const headers = { + authorization: naverResponse.data.access_token, + }; + const result = await axios.post(`${API_PATH}/login/NAVER`, {}, { + headers, + }); + sessionStorage.setItem('accessToken', result.data.accessToken); + localStorage.setItem('refreshToken', result.data.refreshToken); + await updateAuth(); + } catch (e) { + // + } + }; + useEffect(() => { + if (location !== undefined) { + snsLogin(); + } else { + // url 오류로 인한 콜백 + navigate('/login'); + } + }); + return ( +
+ ); +} diff --git a/yarn.lock b/yarn.lock index 6a0cf345..61d68ccb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7589,6 +7589,13 @@ qs@6.10.3: dependencies: side-channel "^1.0.4" +qs@^6.11.2: + version "6.11.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" + integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== + dependencies: + side-channel "^1.0.4" + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"