@@ -4,90 +4,83 @@ import type { NextRequest } from 'next/server';
44export async function middleware ( request : NextRequest ) {
55 const { pathname } = request . nextUrl ;
66
7- // /admin/dashboard 경로에 대한 인증 확인
8- if ( pathname . startsWith ( '/admin/dashboard' ) && ! pathname . startsWith ( '/admin/dashboard/auth' ) ) {
9- console . log ( 'Middleware: Checking auth for:' , pathname ) ;
10-
11- // 모든 쿠키 로그
12- const allCookies = request . cookies . getAll ( ) ;
13- console . log ( 'Middleware: All cookies:' , allCookies ) ;
14-
15- // 여러 방법으로 토큰 읽기 시도
16- const token = request . cookies . get ( 'auth_token' ) ?. value ;
17- const cookieHeader = request . headers . get ( 'cookie' ) ;
18- console . log ( 'Middleware: Raw cookie header:' , cookieHeader ) ;
19- console . log ( 'Middleware: auth_token value:' , token ? `Found token (${ token . length } chars)` : 'No token' ) ;
20-
21- if ( ! token ) {
22- console . log ( 'Middleware: No token found, redirecting to login' ) ;
23- // 토큰이 없으면 로그인 페이지로 리다이렉트
7+ // 정적 자원 및 로그인 페이지는 미들웨어 체크 제외 (matcher에서도 처리하지만 이중 안전장치)
8+ if (
9+ pathname . startsWith ( '/_next' ) ||
10+ pathname . startsWith ( '/static' ) ||
11+ pathname . startsWith ( '/auth/login' ) ||
12+ pathname === '/favicon.ico' ||
13+ pathname === '/windeath44/windeath44.png'
14+ ) {
15+ return NextResponse . next ( ) ;
16+ }
17+
18+ console . log ( 'Middleware: Checking auth for:' , pathname ) ;
19+
20+ // auth_token 쿠키 확인
21+ const token = request . cookies . get ( 'auth_token' ) ?. value ;
22+
23+ if ( ! token ) {
24+ console . log ( 'Middleware: No token found, redirecting to login' ) ;
25+ const loginUrl = new URL ( '/admin/dashboard/auth/login' , request . url ) ;
26+ // 로그인 후 원래 페이지로 돌아오기 위해 callbackUrl 추가 가능 (선택 사항)
27+ // loginUrl.searchParams.set('callbackUrl', pathname);
28+ return NextResponse . redirect ( loginUrl ) ;
29+ }
30+
31+ // 서버 사이드에서 토큰 검증 및 ADMIN 역할 확인
32+ try {
33+ const response = await fetch ( 'https://prod.windeath44.wiki/api/users/profile' , {
34+ method : 'GET' ,
35+ headers : {
36+ 'Authorization' : `Bearer ${ token } ` ,
37+ 'User-Agent' : 'windeath44-admin-middleware' ,
38+ } ,
39+ cache : 'no-store' ,
40+ } ) ;
41+
42+ if ( ! response . ok ) {
43+ console . log ( 'Token validation failed in middleware:' , response . status ) ;
2444 const loginUrl = new URL ( '/admin/dashboard/auth/login' , request . url ) ;
25- return NextResponse . redirect ( loginUrl ) ;
45+ const redirectResponse = NextResponse . redirect ( loginUrl ) ;
46+ redirectResponse . cookies . set ( 'auth_token' , '' , { expires : new Date ( 0 ) } ) ;
47+ return redirectResponse ;
2648 }
27-
28- // 서버 사이드에서 토큰 검증 및 ADMIN 역할 확인
29- try {
30- const response = await fetch ( 'https://prod.windeath44.wiki/api/users/profile' , {
31- method : 'GET' ,
32- headers : {
33- 'Authorization' : `Bearer ${ token } ` ,
34- 'User-Agent' : 'windeath44-admin-middleware' ,
35- } ,
36- // Edge Runtime에서는 cache 옵션 사용
37- cache : 'no-store' ,
38- } ) ;
39-
40- if ( ! response . ok ) {
41- console . log ( 'Token validation failed in middleware:' , response . status ) ;
42- // 토큰이 유효하지 않으면 로그인 페이지로 리다이렉트하고 토큰 삭제
43- const loginUrl = new URL ( '/admin/dashboard/auth/login' , request . url ) ;
44- const redirectResponse = NextResponse . redirect ( loginUrl ) ;
45- redirectResponse . cookies . set ( 'auth_token' , '' , { expires : new Date ( 0 ) } ) ;
46- return redirectResponse ;
47- }
48-
49- const userProfile = await response . json ( ) ;
50- console . log ( 'Middleware: API response:' , JSON . stringify ( userProfile , null , 2 ) ) ;
51-
52- // role은 data 객체 안에 중첩되어 있음
53- const userRole = userProfile . data ?. role ;
54- console . log ( 'Middleware: User role found:' , userRole ) ;
55-
56- if ( userRole !== 'ADMIN' ) {
57- console . log ( 'User does not have ADMIN role in middleware:' , userRole ) ;
58- // ADMIN 역할이 아니면 로그인 페이지로 리다이렉트하고 토큰 삭제
59- const loginUrl = new URL ( '/admin/dashboard/auth/login' , request . url ) ;
60- loginUrl . searchParams . set ( 'access_denied' , 'true' ) ;
61- const redirectResponse = NextResponse . redirect ( loginUrl ) ;
62- redirectResponse . cookies . set ( 'auth_token' , '' , { expires : new Date ( 0 ) } ) ;
63- return redirectResponse ;
64- }
65-
66- // 유효한 ADMIN 토큰이면 진행
67- console . log ( 'Valid ADMIN token verified in middleware' ) ;
68- return NextResponse . next ( ) ;
69-
70- } catch ( error ) {
71- console . error ( 'Token validation error in middleware:' , error ) ;
72- // 에러 발생 시 로그인 페이지로 리다이렉트하고 토큰 삭제
49+
50+ const userProfile = await response . json ( ) ;
51+ const userRole = userProfile . data ?. role ;
52+
53+ if ( userRole !== 'ADMIN' ) {
54+ console . log ( 'User does not have ADMIN role in middleware:' , userRole ) ;
7355 const loginUrl = new URL ( '/admin/dashboard/auth/login' , request . url ) ;
56+ loginUrl . searchParams . set ( 'access_denied' , 'true' ) ;
7457 const redirectResponse = NextResponse . redirect ( loginUrl ) ;
7558 redirectResponse . cookies . set ( 'auth_token' , '' , { expires : new Date ( 0 ) } ) ;
7659 return redirectResponse ;
7760 }
78- }
7961
80- // 기본 /admin 경로는 /admin/dashboard로 리다이렉트
81- if ( pathname === '/admin' ) {
82- const dashboardUrl = new URL ( '/admin/dashboard' , request . url ) ;
83- return NextResponse . redirect ( dashboardUrl ) ;
84- }
62+ // 유효한 ADMIN 토큰이면 진행
63+ return NextResponse . next ( ) ;
8564
86- return NextResponse . next ( ) ;
65+ } catch ( error ) {
66+ console . error ( 'Token validation error in middleware:' , error ) ;
67+ const loginUrl = new URL ( '/admin/dashboard/auth/login' , request . url ) ;
68+ const redirectResponse = NextResponse . redirect ( loginUrl ) ;
69+ redirectResponse . cookies . set ( 'auth_token' , '' , { expires : new Date ( 0 ) } ) ;
70+ return redirectResponse ;
71+ }
8772}
8873
8974export const config = {
9075 matcher : [
91- '/admin/:path*' ,
76+ /*
77+ * Match all request paths except for the ones starting with:
78+ * - api (API routes)
79+ * - _next/static (static files)
80+ * - _next/image (image optimization files)
81+ * - favicon.ico (favicon file)
82+ * - auth/login (login page)
83+ */
84+ '/((?!_next/static|_next/image|favicon.ico|auth/login).*)' ,
9285 ] ,
9386} ;
0 commit comments