@thinkingcat/auth-utils 1.0.21 → 1.0.23
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 +66 -28
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -419,14 +419,21 @@ async function createAuthResponse(accessToken, secret, options) {
|
|
|
419
419
|
const { payload } = tokenResult;
|
|
420
420
|
// 2. NextAuth JWT 생성
|
|
421
421
|
const jwt = createNextAuthJWT(payload, serviceId);
|
|
422
|
+
// refreshToken 추가
|
|
423
|
+
if (refreshToken) {
|
|
424
|
+
jwt.refreshToken = refreshToken;
|
|
425
|
+
}
|
|
426
|
+
// accessTokenExpires 추가 (15분)
|
|
427
|
+
jwt.accessTokenExpires = Date.now() + (15 * 60 * 1000);
|
|
422
428
|
debugLog('createAuthResponse', 'JWT created:', {
|
|
423
429
|
hasId: !!jwt.id,
|
|
424
430
|
hasEmail: !!jwt.email,
|
|
425
431
|
hasRole: !!jwt.role,
|
|
432
|
+
hasRefreshToken: !!jwt.refreshToken,
|
|
426
433
|
});
|
|
427
|
-
// 3. NextAuth
|
|
428
|
-
|
|
429
|
-
debugLog('createAuthResponse', '
|
|
434
|
+
// 3. NextAuth session cookie 생성
|
|
435
|
+
const nextAuthToken = await encodeNextAuthToken(jwt, secret);
|
|
436
|
+
debugLog('createAuthResponse', 'NextAuth session token encoded');
|
|
430
437
|
// 5. HTML 생성
|
|
431
438
|
const displayText = text || serviceId;
|
|
432
439
|
const html = redirectPath
|
|
@@ -440,7 +447,23 @@ async function createAuthResponse(accessToken, secret, options) {
|
|
|
440
447
|
'Content-Type': 'text/html',
|
|
441
448
|
},
|
|
442
449
|
});
|
|
443
|
-
// 4.
|
|
450
|
+
// 4. NextAuth session cookie 설정
|
|
451
|
+
const nextAuthCookieName = isProduction
|
|
452
|
+
? '__Secure-next-auth.session-token'
|
|
453
|
+
: 'next-auth.session-token';
|
|
454
|
+
const cookieOptions = {
|
|
455
|
+
httpOnly: true,
|
|
456
|
+
secure: isProduction,
|
|
457
|
+
sameSite: isProduction ? 'none' : 'lax',
|
|
458
|
+
path: '/',
|
|
459
|
+
maxAge: 30 * 24 * 60 * 60, // 30일
|
|
460
|
+
};
|
|
461
|
+
if (cookieDomain) {
|
|
462
|
+
cookieOptions.domain = cookieDomain;
|
|
463
|
+
}
|
|
464
|
+
response.cookies.set(nextAuthCookieName, nextAuthToken, cookieOptions);
|
|
465
|
+
debugLog('createAuthResponse', 'NextAuth session cookie set:', nextAuthCookieName);
|
|
466
|
+
// 5. 커스텀 토큰 쿠키 설정
|
|
444
467
|
if (refreshToken) {
|
|
445
468
|
setCustomTokens(response, accessToken, refreshToken, {
|
|
446
469
|
cookiePrefix,
|
|
@@ -886,22 +909,44 @@ async function handleJWTCallback(token, user, account, options) {
|
|
|
886
909
|
debugLog('handleJWTCallback', 'Initial login, creating token from user data');
|
|
887
910
|
return createInitialJWTToken(token, user, account);
|
|
888
911
|
}
|
|
889
|
-
// 2. 토큰
|
|
912
|
+
// 2. 커스텀 토큰 쿠키 우선 체크 (middleware에서 refresh한 토큰이 있을 수 있음)
|
|
913
|
+
if (secret && licenseKey && serviceId) {
|
|
914
|
+
const cookieNameToUse = cookieName || `${serviceId}_access_token`;
|
|
915
|
+
debugLog('handleJWTCallback', 'Checking custom token cookie first:', cookieNameToUse);
|
|
916
|
+
const customJwt = await getJWTFromCustomTokenCookie(cookieNameToUse, secret, serviceId, licenseKey);
|
|
917
|
+
if (customJwt) {
|
|
918
|
+
debugLog('handleJWTCallback', 'Found valid custom token cookie, using it');
|
|
919
|
+
// refreshToken이 있으면 유지
|
|
920
|
+
if (token.refreshToken) {
|
|
921
|
+
customJwt.refreshToken = token.refreshToken;
|
|
922
|
+
}
|
|
923
|
+
return customJwt;
|
|
924
|
+
}
|
|
925
|
+
debugLog('handleJWTCallback', 'No valid custom token cookie found');
|
|
926
|
+
}
|
|
927
|
+
// 3. 토큰 유효성 체크
|
|
890
928
|
const now = Date.now();
|
|
891
929
|
const expires = token.accessTokenExpires;
|
|
892
930
|
const hasValidToken = token.id && expires && expires > now;
|
|
893
931
|
const refreshToken = token.refreshToken;
|
|
894
|
-
|
|
932
|
+
debugLog('handleJWTCallback', 'Token status:', {
|
|
933
|
+
hasId: !!token.id,
|
|
934
|
+
hasExpires: !!expires,
|
|
935
|
+
expiresIn: expires ? Math.round((expires - now) / 1000) + 's' : 'N/A',
|
|
936
|
+
hasValidToken,
|
|
937
|
+
hasRefreshToken: !!refreshToken,
|
|
938
|
+
});
|
|
939
|
+
// 3-1. nextauth token이 있고 만료되지 않았으면 그대로 사용
|
|
895
940
|
if (hasValidToken) {
|
|
896
941
|
debugLog('handleJWTCallback', 'Token is still valid, using existing token');
|
|
897
942
|
return token;
|
|
898
943
|
}
|
|
899
|
-
//
|
|
944
|
+
// 3-2. nextauth token이 없거나 만료됨 → refresh token으로 갱신 시도
|
|
900
945
|
// (refreshToken이 있고 SSO 설정이 있을 때만)
|
|
901
946
|
if (refreshToken && ssoBaseURL && authServiceKey && secret) {
|
|
902
|
-
debugLog('handleJWTCallback', 'Token invalid or expired, attempting refresh');
|
|
947
|
+
debugLog('handleJWTCallback', 'Token invalid or expired, attempting SSO refresh');
|
|
903
948
|
try {
|
|
904
|
-
debugLog('handleJWTCallback', 'Calling SSO refresh endpoint');
|
|
949
|
+
debugLog('handleJWTCallback', 'Calling SSO refresh endpoint:', `${ssoBaseURL}/api/sso/refresh`);
|
|
905
950
|
const response = await fetch(`${ssoBaseURL}/api/sso/refresh`, {
|
|
906
951
|
method: 'POST',
|
|
907
952
|
headers: {
|
|
@@ -910,10 +955,11 @@ async function handleJWTCallback(token, user, account, options) {
|
|
|
910
955
|
},
|
|
911
956
|
body: JSON.stringify({ refreshToken }),
|
|
912
957
|
});
|
|
958
|
+
debugLog('handleJWTCallback', 'SSO refresh response status:', response.status);
|
|
913
959
|
if (response.ok) {
|
|
914
960
|
const result = await response.json();
|
|
915
961
|
if (result.success && result.accessToken) {
|
|
916
|
-
debugLog('handleJWTCallback', 'Successfully refreshed token');
|
|
962
|
+
debugLog('handleJWTCallback', 'Successfully refreshed token from SSO');
|
|
917
963
|
// 새 액세스 토큰 검증 및 페이로드 추출
|
|
918
964
|
const tokenResult = await verifyToken(result.accessToken, secret);
|
|
919
965
|
if (tokenResult) {
|
|
@@ -926,35 +972,27 @@ async function handleJWTCallback(token, user, account, options) {
|
|
|
926
972
|
}
|
|
927
973
|
}
|
|
928
974
|
}
|
|
929
|
-
debugLog('handleJWTCallback', 'Failed to refresh token
|
|
975
|
+
debugLog('handleJWTCallback', 'Failed to refresh token from SSO');
|
|
930
976
|
}
|
|
931
977
|
catch (error) {
|
|
932
978
|
console.error('[handleJWTCallback] Error refreshing token:', error);
|
|
933
979
|
}
|
|
934
980
|
}
|
|
935
981
|
else {
|
|
936
|
-
debugLog('handleJWTCallback', 'Cannot refresh - missing
|
|
982
|
+
debugLog('handleJWTCallback', 'Cannot refresh - missing requirements:', {
|
|
983
|
+
hasRefreshToken: !!refreshToken,
|
|
984
|
+
hasSSO: !!ssoBaseURL,
|
|
985
|
+
hasAuthKey: !!authServiceKey,
|
|
986
|
+
hasSecret: !!secret,
|
|
987
|
+
});
|
|
937
988
|
}
|
|
938
|
-
//
|
|
989
|
+
// 4. refresh 실패 시 - 기존 토큰이 있으면 반환
|
|
939
990
|
if (token.id) {
|
|
940
991
|
debugLog('handleJWTCallback', 'Refresh failed, returning existing token (possibly expired)');
|
|
941
992
|
return token;
|
|
942
993
|
}
|
|
943
|
-
//
|
|
944
|
-
debugLog('handleJWTCallback', '
|
|
945
|
-
if (secret && licenseKey && serviceId) {
|
|
946
|
-
const cookieNameToUse = cookieName || `${serviceId}_access_token`;
|
|
947
|
-
const jwt = await getJWTFromCustomTokenCookie(cookieNameToUse, secret, serviceId, licenseKey);
|
|
948
|
-
if (jwt) {
|
|
949
|
-
debugLog('handleJWTCallback', 'Successfully created JWT from custom token cookie');
|
|
950
|
-
return jwt;
|
|
951
|
-
}
|
|
952
|
-
debugLog('handleJWTCallback', 'Failed to create JWT from custom token cookie');
|
|
953
|
-
}
|
|
954
|
-
else {
|
|
955
|
-
debugLog('handleJWTCallback', 'Missing required parameters for custom token reading');
|
|
956
|
-
}
|
|
957
|
-
debugLog('handleJWTCallback', 'Returning original token');
|
|
994
|
+
// 5. 모든 시도 실패 - 빈 토큰 반환
|
|
995
|
+
debugLog('handleJWTCallback', 'All attempts failed, returning empty token');
|
|
958
996
|
return token;
|
|
959
997
|
}
|
|
960
998
|
/**
|
package/package.json
CHANGED