@thinkingcat/auth-utils 1.0.42 → 1.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +116 -42
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -464,28 +464,62 @@ async function createAuthResponse(accessToken, secret, options) {
|
|
|
464
464
|
const nextAuthCookieName = isProduction
|
|
465
465
|
? '__Secure-next-auth.session-token'
|
|
466
466
|
: 'next-auth.session-token';
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
467
|
+
let nextAuthCookieSet = false;
|
|
468
|
+
let retryCount = 0;
|
|
469
|
+
const maxRetries = 3;
|
|
470
|
+
while (!nextAuthCookieSet && retryCount < maxRetries) {
|
|
471
|
+
try {
|
|
472
|
+
const nextAuthToken = await encodeNextAuthToken(jwt, secret);
|
|
473
|
+
if (!nextAuthToken || nextAuthToken.length === 0) {
|
|
474
|
+
throw new Error('Encoded token is empty');
|
|
475
|
+
}
|
|
476
|
+
const cookieOptions = {
|
|
477
|
+
httpOnly: true,
|
|
478
|
+
secure: isProduction,
|
|
479
|
+
sameSite: isProduction ? 'none' : 'lax',
|
|
480
|
+
path: '/',
|
|
481
|
+
maxAge: 30 * 24 * 60 * 60, // 30일
|
|
482
|
+
};
|
|
483
|
+
if (cookieDomain) {
|
|
484
|
+
cookieOptions.domain = cookieDomain;
|
|
485
|
+
}
|
|
486
|
+
response.cookies.set(nextAuthCookieName, nextAuthToken, cookieOptions);
|
|
487
|
+
// 쿠키가 제대로 설정되었는지 검증
|
|
488
|
+
const setCookie = response.cookies.get(nextAuthCookieName);
|
|
489
|
+
if (setCookie && setCookie.value === nextAuthToken) {
|
|
490
|
+
nextAuthCookieSet = true;
|
|
491
|
+
debugLog('createAuthResponse', 'NextAuth session cookie set successfully:', {
|
|
492
|
+
name: nextAuthCookieName,
|
|
493
|
+
valueLength: nextAuthToken.length,
|
|
494
|
+
hasRefreshToken: !!refreshToken,
|
|
495
|
+
retryCount,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
throw new Error('Cookie verification failed after setting');
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
catch (error) {
|
|
503
|
+
retryCount++;
|
|
504
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
505
|
+
debugError('createAuthResponse', `Failed to set NextAuth cookie (attempt ${retryCount}/${maxRetries}):`, error);
|
|
506
|
+
if (retryCount >= maxRetries) {
|
|
507
|
+
console.error('[createAuthResponse] CRITICAL: Failed to set NextAuth cookie after all retries:', {
|
|
508
|
+
error: errorMessage,
|
|
509
|
+
cookieName: nextAuthCookieName,
|
|
510
|
+
hasJWT: !!jwt,
|
|
511
|
+
jwtId: jwt?.id,
|
|
512
|
+
});
|
|
513
|
+
// 최종 실패 시에도 로그를 남기고 계속 진행 (커스텀 토큰으로는 작동 가능)
|
|
514
|
+
}
|
|
515
|
+
else {
|
|
516
|
+
// 재시도 전에 짧은 대기
|
|
517
|
+
await new Promise(resolve => setTimeout(resolve, 100 * retryCount));
|
|
518
|
+
}
|
|
478
519
|
}
|
|
479
|
-
response.cookies.set(nextAuthCookieName, nextAuthToken, cookieOptions);
|
|
480
|
-
debugLog('createAuthResponse', 'NextAuth session cookie set:', {
|
|
481
|
-
name: nextAuthCookieName,
|
|
482
|
-
valueLength: nextAuthToken.length,
|
|
483
|
-
hasRefreshToken: !!refreshToken,
|
|
484
|
-
});
|
|
485
520
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
// NextAuth 쿠키 실패해도 커스텀 토큰으로는 작동 가능
|
|
521
|
+
if (!nextAuthCookieSet) {
|
|
522
|
+
console.warn('[createAuthResponse] WARNING: NextAuth cookie not set, but continuing with custom tokens');
|
|
489
523
|
}
|
|
490
524
|
// 5. 커스텀 토큰 쿠키 설정
|
|
491
525
|
if (refreshToken) {
|
|
@@ -668,30 +702,64 @@ async function verifyAndRefreshToken(req, secret, options) {
|
|
|
668
702
|
}
|
|
669
703
|
jwt.accessTokenExpires = Date.now() + (15 * 60 * 1000);
|
|
670
704
|
// NextAuth 세션 쿠키 생성 (NextAuth encode() 우선 사용)
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
705
|
+
const nextAuthCookieName = isProduction
|
|
706
|
+
? '__Secure-next-auth.session-token'
|
|
707
|
+
: 'next-auth.session-token';
|
|
708
|
+
let nextAuthCookieSet = false;
|
|
709
|
+
let retryCount = 0;
|
|
710
|
+
const maxRetries = 3;
|
|
711
|
+
while (!nextAuthCookieSet && retryCount < maxRetries) {
|
|
712
|
+
try {
|
|
713
|
+
const nextAuthToken = await encodeNextAuthToken(jwt, secret);
|
|
714
|
+
if (!nextAuthToken || nextAuthToken.length === 0) {
|
|
715
|
+
throw new Error('Encoded token is empty');
|
|
716
|
+
}
|
|
717
|
+
const cookieOptions = {
|
|
718
|
+
httpOnly: true,
|
|
719
|
+
secure: isProduction,
|
|
720
|
+
sameSite: isProduction ? 'none' : 'lax',
|
|
721
|
+
path: '/',
|
|
722
|
+
maxAge: 30 * 24 * 60 * 60,
|
|
723
|
+
};
|
|
724
|
+
if (cookieDomain) {
|
|
725
|
+
cookieOptions.domain = cookieDomain;
|
|
726
|
+
}
|
|
727
|
+
response.cookies.set(nextAuthCookieName, nextAuthToken, cookieOptions);
|
|
728
|
+
// 쿠키가 제대로 설정되었는지 검증
|
|
729
|
+
const setCookie = response.cookies.get(nextAuthCookieName);
|
|
730
|
+
if (setCookie && setCookie.value === nextAuthToken) {
|
|
731
|
+
nextAuthCookieSet = true;
|
|
732
|
+
debugLog('verifyAndRefreshToken', 'NextAuth session cookie set successfully:', {
|
|
733
|
+
name: nextAuthCookieName,
|
|
734
|
+
valueLength: nextAuthToken.length,
|
|
735
|
+
retryCount,
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
throw new Error('Cookie verification failed after setting');
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
catch (error) {
|
|
743
|
+
retryCount++;
|
|
744
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
745
|
+
debugError('verifyAndRefreshToken', `Failed to set NextAuth cookie (attempt ${retryCount}/${maxRetries}):`, error);
|
|
746
|
+
if (retryCount >= maxRetries) {
|
|
747
|
+
console.error('[verifyAndRefreshToken] CRITICAL: Failed to set NextAuth cookie after all retries:', {
|
|
748
|
+
error: errorMessage,
|
|
749
|
+
cookieName: nextAuthCookieName,
|
|
750
|
+
hasJWT: !!jwt,
|
|
751
|
+
jwtId: jwt?.id,
|
|
752
|
+
});
|
|
753
|
+
// 최종 실패 시에도 로그를 남기고 계속 진행
|
|
754
|
+
}
|
|
755
|
+
else {
|
|
756
|
+
// 재시도 전에 짧은 대기
|
|
757
|
+
await new Promise(resolve => setTimeout(resolve, 100 * retryCount));
|
|
758
|
+
}
|
|
685
759
|
}
|
|
686
|
-
response.cookies.set(nextAuthCookieName, nextAuthToken, cookieOptions);
|
|
687
|
-
debugLog('verifyAndRefreshToken', 'NextAuth session cookie set:', {
|
|
688
|
-
name: nextAuthCookieName,
|
|
689
|
-
valueLength: nextAuthToken.length,
|
|
690
|
-
});
|
|
691
760
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
// Continue even if NextAuth cookie fails
|
|
761
|
+
if (!nextAuthCookieSet) {
|
|
762
|
+
console.warn('[verifyAndRefreshToken] WARNING: NextAuth cookie not set, but continuing with custom tokens');
|
|
695
763
|
}
|
|
696
764
|
// 커스텀 토큰 쿠키 설정
|
|
697
765
|
if (newRefreshToken) {
|
|
@@ -1549,8 +1617,14 @@ async function handleMiddleware(req, config, options) {
|
|
|
1549
1617
|
// 2. 루트 경로 처리 - SSO 토큰 처리 (인증 체크보다 먼저!)
|
|
1550
1618
|
if (pathname === '/') {
|
|
1551
1619
|
const tokenParam = req.nextUrl.searchParams.get('token');
|
|
1620
|
+
console.log('[handleMiddleware] Root path check:', {
|
|
1621
|
+
pathname,
|
|
1622
|
+
hasTokenParam: !!tokenParam,
|
|
1623
|
+
tokenLength: tokenParam?.length || 0,
|
|
1624
|
+
});
|
|
1552
1625
|
if (tokenParam) {
|
|
1553
1626
|
debugLog('handleMiddleware', 'Processing SSO token from query parameter');
|
|
1627
|
+
console.log('[handleMiddleware] Processing SSO token from query parameter');
|
|
1554
1628
|
try {
|
|
1555
1629
|
// 1. 토큰 검증
|
|
1556
1630
|
const tokenResult = await verifyToken(tokenParam, secret);
|
package/package.json
CHANGED