@thinkingcat/auth-utils 1.0.44 → 1.0.46
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 +27 -119
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -164,10 +164,16 @@ function createNextAuthJWT(payload, serviceId) {
|
|
|
164
164
|
const services = payload.services || [];
|
|
165
165
|
const service = services.find((s) => s.serviceId === serviceId);
|
|
166
166
|
const effectiveRole = service?.role || payload.role || 'ADMIN';
|
|
167
|
+
// name 필드 결정: payload.name이 있으면 사용, 없으면 decryptedEmail 또는 maskedEmail 사용
|
|
168
|
+
// email은 암호화되어 있을 수 있으므로 직접 사용하지 않음
|
|
169
|
+
const displayName = payload.name
|
|
170
|
+
|| payload.decryptedEmail
|
|
171
|
+
|| payload.maskedEmail
|
|
172
|
+
|| 'User';
|
|
167
173
|
const jwt = {
|
|
168
174
|
id: (payload.id || payload.sub),
|
|
169
175
|
email: payload.email,
|
|
170
|
-
name:
|
|
176
|
+
name: displayName,
|
|
171
177
|
role: effectiveRole, // Role enum 타입 (string으로 캐스팅)
|
|
172
178
|
services: payload.services,
|
|
173
179
|
phoneVerified: payload.phoneVerified ?? false,
|
|
@@ -460,67 +466,22 @@ async function createAuthResponse(accessToken, secret, options) {
|
|
|
460
466
|
const response = redirectPath
|
|
461
467
|
? NextResponseClass.redirect(new URL(redirectPath, req.url), { status: 302 })
|
|
462
468
|
: NextResponseClass.json({ success: true, message: text || 'Authentication successful' }, { status: 200 });
|
|
463
|
-
// 4. NextAuth 세션 쿠키 생성
|
|
469
|
+
// 4. NextAuth 세션 쿠키 생성
|
|
470
|
+
// 주의: NextAuth는 세션 쿠키를 자동으로 관리하므로, 직접 설정하는 것이 문제를 일으킬 수 있습니다.
|
|
471
|
+
// 하지만 미들웨어에서는 NextAuth의 정상 플로우를 사용할 수 없으므로,
|
|
472
|
+
// NextAuth의 encode()와 decode()가 호환되도록 주의해야 합니다.
|
|
464
473
|
const nextAuthCookieName = isProduction
|
|
465
474
|
? '__Secure-next-auth.session-token'
|
|
466
475
|
: 'next-auth.session-token';
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
if (!nextAuthCookieSet) {
|
|
522
|
-
console.warn('[createAuthResponse] WARNING: NextAuth cookie not set, but continuing with custom tokens');
|
|
523
|
-
}
|
|
476
|
+
// NextAuth 세션 쿠키 설정을 건너뛰고 커스텀 토큰만 사용
|
|
477
|
+
// NextAuth는 JWT 콜백을 통해 자동으로 세션 쿠키를 생성하므로,
|
|
478
|
+
// 미들웨어에서 직접 설정하면 NextAuth가 디코딩할 수 없는 경우가 있습니다.
|
|
479
|
+
// 따라서 커스텀 토큰만 설정하고, NextAuth 세션은 JWT 콜백에서 처리하도록 합니다.
|
|
480
|
+
debugLog('createAuthResponse', 'Skipping NextAuth session cookie - will be handled by NextAuth JWT callback', {
|
|
481
|
+
name: nextAuthCookieName,
|
|
482
|
+
hasJWT: !!jwt,
|
|
483
|
+
jwtId: jwt?.id,
|
|
484
|
+
});
|
|
524
485
|
// 5. 커스텀 토큰 쿠키 설정
|
|
525
486
|
if (refreshToken) {
|
|
526
487
|
setCustomTokens(response, accessToken, refreshToken, {
|
|
@@ -701,66 +662,13 @@ async function verifyAndRefreshToken(req, secret, options) {
|
|
|
701
662
|
jwt.refreshToken = newRefreshToken;
|
|
702
663
|
}
|
|
703
664
|
jwt.accessTokenExpires = Date.now() + (15 * 60 * 1000);
|
|
704
|
-
// NextAuth 세션 쿠키 생성
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
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
|
-
}
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
if (!nextAuthCookieSet) {
|
|
762
|
-
console.warn('[verifyAndRefreshToken] WARNING: NextAuth cookie not set, but continuing with custom tokens');
|
|
763
|
-
}
|
|
665
|
+
// NextAuth 세션 쿠키 생성
|
|
666
|
+
// 주의: NextAuth는 세션 쿠키를 자동으로 관리하므로, 직접 설정하는 것이 문제를 일으킬 수 있습니다.
|
|
667
|
+
// 따라서 커스텀 토큰만 설정하고, NextAuth 세션은 JWT 콜백에서 처리하도록 합니다.
|
|
668
|
+
debugLog('verifyAndRefreshToken', 'Skipping NextAuth session cookie - will be handled by NextAuth JWT callback', {
|
|
669
|
+
hasJWT: !!jwt,
|
|
670
|
+
jwtId: jwt?.id,
|
|
671
|
+
});
|
|
764
672
|
// 커스텀 토큰 쿠키 설정
|
|
765
673
|
if (newRefreshToken) {
|
|
766
674
|
setCustomTokens(response, refreshResult.accessToken, newRefreshToken, {
|
package/package.json
CHANGED