Skip to content

Commit

Permalink
๐Ÿ› Fix : ์†Œ์…œ๋กœ๊ทธ์ธ ์ฝœ๋ฐฑํŽ˜์ด์ง€ ์ˆ˜์ •
Browse files Browse the repository at this point in the history
- #QTVY-152
  • Loading branch information
seon022 committed Dec 9, 2024
1 parent ba48573 commit b9b99b6
Show file tree
Hide file tree
Showing 14 changed files with 148 additions and 139 deletions.
50 changes: 18 additions & 32 deletions src/app/(empty-layout)/(auth)/login/callback/page.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,53 @@
'use client';

import { useAuthStore } from '@/entities/user';
import { userService } from '@/entities/user/api/userService';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { toast } from 'react-toastify';
import { useAuthStore } from '@/entities/User';
import { userService } from '@/entities/User/api/userService';

export default function LoginCallbackPage() {
const router = useRouter();
const { socialLoginComplete } = useAuthStore();

useEffect(() => {
const handleSocialLoginCallback = async () => {
const handleKakaoLoginCallback = async () => {
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');
const provider = urlParams.get('provider');

const savedState = localStorage.getItem(`oauth_state_${provider}`);
// state ๊ฒ€์ฆ
const savedState = localStorage.getItem('kakao_oauth_state');
if (!state || state !== savedState) {
toast.error('์ธ์ฆ ์ƒํƒœ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.');
router.push('/login');
return;
}

if (!code || !provider) {
if (!code) {
toast.error('์œ ํšจํ•˜์ง€ ์•Š์€ ์ธ์ฆ ์ •๋ณด์ž…๋‹ˆ๋‹ค.');
router.push('/login');
return;
}

try {
const result = await userService.socialLoginCallback({
provider,
code,
state
});
const result = await userService.kakaoLoginCallback(code, state);
await socialLoginComplete(result);

if (result) {
await socialLoginComplete(result);
toast.success('๋กœ๊ทธ์ธ ์„ฑ๊ณต');
// state ์ œ๊ฑฐ
localStorage.removeItem('kakao_oauth_state');

// ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€ ์ƒํƒœ ์ดˆ๊ธฐํ™”
localStorage.removeItem(`oauth_state_${provider}`);

router.push('/');
} else {
throw new Error('๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.');
}
toast.success('์นด์นด์˜ค ๋กœ๊ทธ์ธ ์„ฑ๊ณต');
router.push('/');
} catch (error) {
console.error('์†Œ์…œ ๋กœ๊ทธ์ธ ์—๋Ÿฌ:', error);

const errorMessage =
error instanceof Error
? error.message
: '์†Œ์…œ ๋กœ๊ทธ์ธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.';

toast.error(errorMessage);
console.error('์นด์นด์˜ค ๋กœ๊ทธ์ธ ์—๋Ÿฌ:', error);
toast.error(
error instanceof Error ? error.message : '์นด์นด์˜ค ๋กœ๊ทธ์ธ ์‹คํŒจ'
);
router.push('/login');
}
};

handleSocialLoginCallback();
handleKakaoLoginCallback();
}, [router, socialLoginComplete]);

return <div>๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ ์ค‘...</div>;
Expand Down
41 changes: 19 additions & 22 deletions src/app/(empty-layout)/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,27 @@ import Image from 'next/image';
import Link from 'next/link';
import { toast } from 'react-toastify';
import useRedirect from '@/features/auth/hooks/useRedirect';
import { SOCIAL_PROVIDERS } from '@/features/auth/model/constants';
import { SocialLoginButton } from '@/features/auth/ui/SocialLoginButton';
import LoginContainer from '@/features/auth/ui/LoginContainer';
import { AxiosError } from 'axios';
import { useAuthStore, SocialProvider } from '@/entities/user';
import { useAuthStore } from '@/entities/user';

export default function LoginPage() {
const { isAuthenticated, userId, tokens, socialLogin } = useAuthStore();
const { isAuthenticated, userId, tokens, kakaoLogin } = useAuthStore();

useRedirect(isAuthenticated, userId, tokens);
const handleSocialLogin = async (provider: SocialProvider) => {

const handleKakaoLogin = async () => {
try {
await socialLogin(provider);
// ์ƒํƒœ(state) ์ƒ์„ฑ ๋ฐ ์ €์žฅ
const state = crypto.randomUUID();
localStorage.setItem('kakao_oauth_state', state);

// ์นด์นด์˜ค ๋กœ๊ทธ์ธ URL๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
await kakaoLogin(state);
} catch (error) {
const errorMsg = error as AxiosError;
console.error(errorMsg);
toast.error('์†Œ์…œ ๋กœ๊ทธ์ธ ์‹คํŒจ');
console.error(error);
toast.error('์นด์นด์˜ค ๋กœ๊ทธ์ธ ์‹คํŒจ');
}
};
const SocialLoginButtons = () => (
<div className="mb-8 mt-8 flex justify-center gap-4">
{SOCIAL_PROVIDERS.map(provider => (
<SocialLoginButton
key={provider.name}
provider={provider}
onLogin={handleSocialLogin}
/>
))}
</div>
);

return (
<div className="item-center flex min-h-[80vh] flex-col justify-center space-y-16 text-center">
Expand All @@ -48,7 +39,13 @@ export default function LoginPage() {
</Link>
</section>
<LoginContainer />
<SocialLoginButtons />
<div className="mb-8 mt-8 flex justify-center gap-4">
<button
onClick={handleKakaoLogin}
className="rounded bg-[#FEE500] px-4 py-2 text-black">
์นด์นด์˜ค ๋กœ๊ทธ์ธ
</button>
</div>
<div className="text-sm text-primary-800">
<Link href={'/signup'}>ํšŒ์›๊ฐ€์ž…</Link>
</div>
Expand Down
38 changes: 0 additions & 38 deletions src/app/(empty-layout)/(auth)/oauth/page.tsx

This file was deleted.

41 changes: 34 additions & 7 deletions src/entities/User/api/userService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { api } from '@/shared/api/client';
import axios, { AxiosError } from 'axios';
import axios from 'axios';
import type {
UserLoginDTO,
UserJoinDTO,
Expand Down Expand Up @@ -43,12 +43,35 @@ export const userService = {
try {
const response = await axiosInstance.post(
`${process.env.NEXT_PUBLIC_API_URL}/api/oauth2/${params.provider}/callback`,
{ provider: params.provider, code: params.code, state: params.state }
{
provider: params.provider,
code: params.code,
state: params.state
}
);

if (!response.data || !response.data.userId) {
throw new Error('์†Œ์…œ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
return {
authentication: 'Bearer',
userId: response.data.userId,
access_token: response.data.accessToken,
refresh_token: response.data.refreshToken
};
} catch (error) {
if (axios.isAxiosError(error)) {
const errorResponse = error.response?.data;
throw new Error(
errorResponse?.message || '์†Œ์…œ ๋กœ๊ทธ์ธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.'
);
}
throw error;
}
},
kakaoLoginCallback: async (code: string, state: string) => {
try {
const response = await axiosInstance.post(
`${process.env.NEXT_PUBLIC_API_URL}/api/oauth2/kakao/callback`,
{ code, state }
);

return {
authentication: 'Bearer',
Expand All @@ -57,11 +80,15 @@ export const userService = {
refresh_token: response.data.refreshToken
};
} catch (error) {
const errorMessage = error as AxiosError;
console.error(errorMessage);
if (axios.isAxiosError(error)) {
const errorResponse = error.response?.data;
throw new Error(
errorResponse?.message || '์นด์นด์˜ค ๋กœ๊ทธ์ธ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.'
);
}
throw error;
}
},

join: async (joinData: UserJoinDTO) => {
if (!joinData.email) {
throw new Error('์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.');
Expand Down
23 changes: 20 additions & 3 deletions src/entities/User/model/store/authStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ export const useAuthStore = create<AuthState>()(
return false;
}
},
socialLogin: async (provider: 'google' | 'kakao' | 'naver') => {
socialLogin: async (provider: SocialProvider, state?: string) => {
try {
const authorizationUrl = `${process.env.NEXT_PUBLIC_API_URL}/api/oauth2/${provider}`;
window.location.href = authorizationUrl;
const authorizationUrl = state
? `${process.env.NEXT_PUBLIC_API_URL}/api/oauth2/${provider}?state=${encodeURIComponent(state)}`
: `${process.env.NEXT_PUBLIC_API_URL}/api/oauth2/${provider}`;

window.location.href = authorizationUrl;
return true;
} catch (error) {
set({
Expand All @@ -75,12 +77,27 @@ export const useAuthStore = create<AuthState>()(
return false;
}
},
kakaoLogin: async (state: string) => {
try {
const authorizationUrl = `${process.env.NEXT_PUBLIC_API_URL}/api/oauth2/kakao?state=${encodeURIComponent(state)}`;
window.location.href = authorizationUrl;
return true;
} catch (error) {
set({
isAuthenticated: false,
isLoading: false,
error: error instanceof Error ? error.message : '์นด์นด์˜ค ๋กœ๊ทธ์ธ ์‹คํŒจ'
});
return false;
}
},
socialLoginComplete: async (loginResponse: {
authentication: string;
access_token: string;
refresh_token: string;
userId: string;
}) => {
// ๊ธฐ์กด ๋กœ๊ทธ์ธ ์™„๋ฃŒ ๋กœ์ง๊ณผ ๋™์ผ
document.cookie = `auth-storage=${JSON.stringify({
state: {
userId: loginResponse.userId,
Expand Down
1 change: 1 addition & 0 deletions src/entities/User/model/types/AuthState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export interface AuthState {
refreshToken: () => Promise<boolean>;
deleteUser: () => Promise<boolean>;
socialLoginComplete: (loginResponse: LoginResponse) => Promise<boolean>;
kakaoLogin: (state: string) => Promise<boolean>;
}
2 changes: 1 addition & 1 deletion src/features/meeting/ui/MeetingDetail/MeetingDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { toast } from 'react-toastify';
import { useMeetingBoardDetail } from '@/features/meeting/model/queries';
import { FullScreenLoading } from '@/shared/ui/components/Loading/Loading';
import ErrorFallback from '@/shared/ui/components/ErrorBoundary/ErrorFallback';
import { useAuthStore } from '@/entities/User/model/store/authStore';
import { MeetingHeader, MeetingInfo, MeetingTabs } from '@/features/meeting';
import Link from 'next/link';
import { useAuthStore } from '@/entities/user';

export default function MeetingDetail() {
const params = useParams();
Expand Down
9 changes: 1 addition & 8 deletions src/features/mypage/ui/MypageTap.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';
import { useMemo, useState } from 'react';
import { UserInfo } from './UserInfo';
import { UserReviews } from '@/features/review/ui/UserReviews';

type ProfileTabType = 'intro' | 'review' | 'favorites';

Expand All @@ -12,8 +11,6 @@ export const MypageTap = () => {
switch (activeTab) {
case 'intro':
return <UserInfo />;
case 'review':
return <UserReviews />;
}
}, [activeTab]);

Expand All @@ -29,11 +26,7 @@ export const MypageTap = () => {
? 'border-b-2 border-primary-800 text-primary-800'
: 'border-b-2 border-white text-gray-500'
}`}>
{tab === 'intro'
? '์†Œ๊ฐœ๊ธ€'
: tab === 'review'
? '๋‚ด ํ›„๊ธฐ'
: '์ฆ๊ฒจ์ฐพ๊ธฐ'}
{tab === 'intro' ? '์†Œ๊ฐœ๊ธ€' : ''}
</button>
))}
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/features/mypage/ui/UserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import Image from 'next/image';
import { LogOut, Pencil } from 'lucide-react';
import { useRouter } from 'next/navigation';
import { useAuthStore } from '@/entities/User';
import { useUserQuery } from '@/entities/User/model/userQueries';
import { useAuthStore } from '@/entities/user';
import { useUserQuery } from '@/entities/user/model/userQueries';

export const UserProfile = () => {
const router = useRouter();
Expand Down
Loading

0 comments on commit b9b99b6

Please sign in to comment.