@thinkingcat/auth-utils 1.0.49 → 2.0.0

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.
@@ -0,0 +1,15 @@
1
+ import type { MiddlewareConfig } from '../types';
2
+ /**
3
+ * 기본 미들웨어 설정을 생성하는 함수
4
+ */
5
+ export declare function createMiddlewareConfig(config: Partial<MiddlewareConfig> & {
6
+ serviceId: string;
7
+ }, defaults?: {
8
+ publicPaths?: string[];
9
+ subscriptionRequiredPaths?: string[];
10
+ subscriptionExemptApiPaths?: string[];
11
+ authApiPaths?: string[];
12
+ rolePaths?: Record<string, string>;
13
+ systemAdminRole?: string;
14
+ errorPath?: string;
15
+ }): Required<Omit<MiddlewareConfig, 'serviceId'>> & Pick<MiddlewareConfig, 'serviceId'>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMiddlewareConfig = createMiddlewareConfig;
4
+ /**
5
+ * 기본 미들웨어 설정을 생성하는 함수
6
+ */
7
+ function createMiddlewareConfig(config, defaults) {
8
+ const defaultPublicPaths = defaults?.publicPaths || [
9
+ '/robots.txt', '/sitemap.xml', '/ads.txt', '/images', '/login', '/register',
10
+ '/forgot-password', '/reset-password', '/about', '/pricing', '/support',
11
+ '/terms', '/privacy', '/refund', '/error'
12
+ ];
13
+ const defaultSubscriptionRequiredPaths = defaults?.subscriptionRequiredPaths || [
14
+ '/admin', '/teacher', '/student', '/personal'
15
+ ];
16
+ const defaultSubscriptionExemptApiPaths = defaults?.subscriptionExemptApiPaths || [
17
+ '/api/auth', '/api/sso', '/api/admin/subscription', '/api/admin/payment-methods'
18
+ ];
19
+ const defaultAuthApiPaths = defaults?.authApiPaths || [
20
+ '/api/auth/send-verification', '/api/auth/verify-code', '/api/auth/verify-user', '/api/auth/select-academy'
21
+ ];
22
+ const defaultRolePaths = defaults?.rolePaths || {
23
+ SYSTEM_ADMIN: '/system', ADMIN: '/admin', TEACHER: '/teacher', STUDENT: '/student'
24
+ };
25
+ const defaultSystemAdminRole = defaults?.systemAdminRole || 'SYSTEM_ADMIN';
26
+ const defaultErrorPath = defaults?.errorPath || '/error';
27
+ return {
28
+ publicPaths: config.publicPaths || defaultPublicPaths,
29
+ subscriptionRequiredPaths: config.subscriptionRequiredPaths || defaultSubscriptionRequiredPaths,
30
+ subscriptionExemptApiPaths: config.subscriptionExemptApiPaths || defaultSubscriptionExemptApiPaths,
31
+ authApiPaths: config.authApiPaths || defaultAuthApiPaths,
32
+ rolePaths: config.rolePaths || defaultRolePaths,
33
+ roleAccessConfig: config.roleAccessConfig || {},
34
+ systemAdminRole: config.systemAdminRole || defaultSystemAdminRole,
35
+ errorPath: config.errorPath || defaultErrorPath,
36
+ serviceId: config.serviceId,
37
+ };
38
+ }
@@ -0,0 +1,6 @@
1
+ import type { NextRequest, NextResponse } from 'next/server';
2
+ import type { MiddlewareConfig, MiddlewareOptions } from '../types';
3
+ /**
4
+ * 통합 미들웨어 핸들러 함수
5
+ */
6
+ export declare function handleMiddleware(req: NextRequest, config: Required<Omit<MiddlewareConfig, 'serviceId'>> & Pick<MiddlewareConfig, 'serviceId'>, options: MiddlewareOptions): Promise<NextResponse | null>;
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.handleMiddleware = handleMiddleware;
37
+ const server_1 = require("../utils/server");
38
+ const license_1 = require("../utils/license");
39
+ const logger_1 = require("../utils/logger");
40
+ const roles_1 = require("../core/roles");
41
+ const verify_1 = require("../core/verify");
42
+ const jwt_1 = require("../core/jwt");
43
+ const api_1 = require("../sso/api");
44
+ const auth_response_1 = require("../core/auth-response");
45
+ const redirect_1 = require("../utils/redirect");
46
+ const cookies_1 = require("../core/cookies");
47
+ /**
48
+ * 통합 미들웨어 핸들러 함수
49
+ */
50
+ async function handleMiddleware(req, config, options) {
51
+ const { NextResponse: NextResponseClass } = await (0, server_1.getNextServer)();
52
+ try {
53
+ const pathname = req.nextUrl.pathname;
54
+ const { secret, isProduction, cookieDomain, getNextAuthToken, licenseKey } = options;
55
+ await (0, license_1.checkLicenseKey)(licenseKey);
56
+ if (!config.serviceId) {
57
+ throw new Error('serviceId is required in middleware config');
58
+ }
59
+ const serviceId = config.serviceId;
60
+ const cookiePrefix = serviceId;
61
+ let token = null;
62
+ if (getNextAuthToken) {
63
+ token = await getNextAuthToken(req);
64
+ }
65
+ else {
66
+ try {
67
+ const { getToken } = await Promise.resolve().then(() => __importStar(require('next-auth/jwt')));
68
+ token = await getToken({ req, secret });
69
+ }
70
+ catch (error) {
71
+ (0, logger_1.debugLog)('handleMiddleware', 'getToken failed', error);
72
+ }
73
+ }
74
+ const effectiveRole = (0, roles_1.getEffectiveRole)(token, serviceId);
75
+ // 1. API 요청 처리
76
+ if (pathname.startsWith('/api/')) {
77
+ if (config.authApiPaths.includes(pathname)) {
78
+ return NextResponseClass.next();
79
+ }
80
+ if (config.subscriptionExemptApiPaths.some((path) => pathname.startsWith(path))) {
81
+ return NextResponseClass.next();
82
+ }
83
+ const authCheck = await (0, verify_1.verifyAndRefreshTokenWithNextAuth)(req, token, secret, {
84
+ cookiePrefix,
85
+ serviceId,
86
+ isProduction,
87
+ cookieDomain,
88
+ text: serviceId,
89
+ ssoBaseURL: options.ssoBaseURL,
90
+ authServiceKey: options.authServiceKey,
91
+ licenseKey: options.licenseKey,
92
+ });
93
+ if (authCheck.response)
94
+ return authCheck.response;
95
+ if (!authCheck.isValid) {
96
+ const response = await (0, redirect_1.redirectToError)(req, 'UNAUTHORIZED', '인증이 필요합니다.', config.errorPath);
97
+ (0, cookies_1.clearAuthCookies)(response, cookiePrefix);
98
+ return response;
99
+ }
100
+ return NextResponseClass.next();
101
+ }
102
+ // 2. 루트 경로 처리 - SSO 토큰 처리
103
+ if (pathname === '/') {
104
+ const tokenParam = req.nextUrl.searchParams.get('token');
105
+ if (tokenParam) {
106
+ try {
107
+ const tokenResult = await (0, jwt_1.verifyToken)(tokenParam, secret);
108
+ if (!tokenResult)
109
+ throw new Error('Invalid token');
110
+ const { payload } = tokenResult;
111
+ const defaultRole = Object.keys(config.rolePaths)[0] || 'ADMIN';
112
+ const tokenRole = (0, jwt_1.extractRoleFromPayload)(payload, serviceId, defaultRole);
113
+ const userId = payload.id || payload.sub || payload.userId || '';
114
+ const ssoBaseURL = options.ssoBaseURL;
115
+ const authServiceKey = options.authServiceKey;
116
+ let refreshToken = '';
117
+ if (authServiceKey && userId) {
118
+ try {
119
+ const refreshTokenResult = await (0, api_1.getRefreshTokenFromSSO)(userId, tokenParam, { ssoBaseURL, authServiceKey });
120
+ refreshToken = refreshTokenResult || '';
121
+ }
122
+ catch (error) {
123
+ (0, logger_1.debugError)('handleMiddleware', 'Failed to get refresh token', error);
124
+ }
125
+ }
126
+ const redirectPath = config.rolePaths[tokenRole] || config.rolePaths[defaultRole] || '/admin';
127
+ return await (0, auth_response_1.createAuthResponse)(tokenParam, secret, {
128
+ req,
129
+ refreshToken: refreshToken || undefined,
130
+ redirectPath,
131
+ text: serviceId,
132
+ cookiePrefix,
133
+ isProduction,
134
+ cookieDomain,
135
+ serviceId,
136
+ licenseKey: options.licenseKey,
137
+ });
138
+ }
139
+ catch (error) {
140
+ (0, logger_1.debugError)('handleMiddleware', 'Error processing token', error);
141
+ const ssoBaseURL = options.ssoBaseURL;
142
+ return await (0, redirect_1.redirectToSSOLogin)(req, serviceId, ssoBaseURL);
143
+ }
144
+ }
145
+ if (token && effectiveRole) {
146
+ return await (0, redirect_1.redirectToRoleDashboard)(req, effectiveRole, config.rolePaths);
147
+ }
148
+ const ssoBaseURL = options.ssoBaseURL;
149
+ return await (0, redirect_1.redirectToSSOLogin)(req, serviceId, ssoBaseURL);
150
+ }
151
+ // 3. 공개 경로 처리
152
+ if (config.publicPaths.some((path) => pathname === path || pathname.startsWith(path))) {
153
+ if (pathname === '/error' || pathname === '/verification') {
154
+ return NextResponseClass.next();
155
+ }
156
+ if (token && effectiveRole) {
157
+ return await (0, redirect_1.redirectToRoleDashboard)(req, effectiveRole, config.rolePaths);
158
+ }
159
+ return NextResponseClass.next();
160
+ }
161
+ // 4. 인증 체크
162
+ const authCheck = await (0, verify_1.verifyAndRefreshTokenWithNextAuth)(req, token, secret, {
163
+ cookiePrefix,
164
+ serviceId,
165
+ isProduction,
166
+ cookieDomain,
167
+ text: serviceId,
168
+ ssoBaseURL: options.ssoBaseURL,
169
+ authServiceKey: options.authServiceKey,
170
+ licenseKey: options.licenseKey,
171
+ });
172
+ if (authCheck.response)
173
+ return authCheck.response;
174
+ if (!authCheck.isValid) {
175
+ const ssoBaseURL = options.ssoBaseURL;
176
+ return await (0, redirect_1.redirectToSSOLogin)(req, serviceId, ssoBaseURL);
177
+ }
178
+ let finalToken = authCheck.token || token;
179
+ if (!finalToken && authCheck.isValid) {
180
+ if (getNextAuthToken) {
181
+ finalToken = await getNextAuthToken(req);
182
+ }
183
+ else {
184
+ try {
185
+ const { getToken } = await Promise.resolve().then(() => __importStar(require('next-auth/jwt')));
186
+ finalToken = await getToken({ req, secret });
187
+ }
188
+ catch {
189
+ // Ignored
190
+ }
191
+ }
192
+ }
193
+ if (!finalToken) {
194
+ const ssoBaseURL = options.ssoBaseURL;
195
+ return await (0, redirect_1.redirectToSSOLogin)(req, serviceId, ssoBaseURL);
196
+ }
197
+ if (finalToken.error === "RefreshAccessTokenError") {
198
+ const ssoBaseURL = options.ssoBaseURL;
199
+ return await (0, redirect_1.redirectToSSOLogin)(req, serviceId, ssoBaseURL);
200
+ }
201
+ if (!finalToken.role || !finalToken.email) {
202
+ const ssoBaseURL = options.ssoBaseURL;
203
+ return await (0, redirect_1.redirectToSSOLogin)(req, serviceId, ssoBaseURL);
204
+ }
205
+ const finalEffectiveRole = finalToken.role || (0, roles_1.getEffectiveRole)(finalToken, serviceId) || effectiveRole || '';
206
+ if (config.roleAccessConfig && Object.keys(config.roleAccessConfig).length > 0 && finalEffectiveRole) {
207
+ const roleCheck = (0, roles_1.checkRoleAccess)(pathname, finalEffectiveRole, config.roleAccessConfig);
208
+ if (!roleCheck.allowed) {
209
+ return await (0, redirect_1.redirectToError)(req, 'ACCESS_DENIED', roleCheck.message || '접근 권한이 없습니다.', config.errorPath);
210
+ }
211
+ }
212
+ if (finalEffectiveRole && (0, roles_1.requiresSubscription)(pathname, finalEffectiveRole, config.subscriptionRequiredPaths, config.systemAdminRole)) {
213
+ const services = finalToken.services || [];
214
+ const ssoBaseURL = options.ssoBaseURL;
215
+ if (!ssoBaseURL)
216
+ throw new Error('ssoBaseURL is required');
217
+ const subscriptionCheck = (0, api_1.validateServiceSubscription)(services, serviceId, ssoBaseURL);
218
+ if (!subscriptionCheck.isValid) {
219
+ return NextResponseClass.redirect(subscriptionCheck.redirectUrl);
220
+ }
221
+ }
222
+ return null;
223
+ }
224
+ catch (error) {
225
+ (0, logger_1.debugError)('handleMiddleware', 'Middleware error', error);
226
+ return await (0, redirect_1.redirectToError)(req, 'INTERNAL_ERROR', '서버 오류가 발생했습니다.', config.errorPath);
227
+ }
228
+ }
@@ -0,0 +1,35 @@
1
+ import type { JWT } from "next-auth/jwt";
2
+ /**
3
+ * JWT 콜백에서 초기 로그인 시 토큰 생성 헬퍼
4
+ */
5
+ export declare function createInitialJWTToken(token: JWT, user: {
6
+ id: string;
7
+ email?: string | null;
8
+ emailHash?: string | null;
9
+ maskedEmail?: string | null;
10
+ phoneHash?: string | null;
11
+ maskedPhone?: string | null;
12
+ role?: string;
13
+ phone?: string | null;
14
+ decryptedEmail?: string | null;
15
+ decryptedPhone?: string | null;
16
+ refreshToken?: string | null;
17
+ }, account?: {
18
+ serviceId?: string;
19
+ } | null): JWT;
20
+ /**
21
+ * 쿠키에서 커스텀 토큰을 읽어서 NextAuth JWT로 변환하는 헬퍼 함수
22
+ */
23
+ export declare function getJWTFromCustomTokenCookie(cookieName: string, secret: string, serviceId: string, licenseKey: string): Promise<JWT | null>;
24
+ /**
25
+ * JWT 콜백을 위한 통합 헬퍼 함수
26
+ */
27
+ export declare function handleJWTCallback(token: JWT, user?: any, account?: any, options?: {
28
+ secret?: string;
29
+ licenseKey?: string;
30
+ serviceId?: string;
31
+ cookieName?: string;
32
+ debug?: boolean;
33
+ ssoBaseURL?: string;
34
+ authServiceKey?: string;
35
+ }): Promise<JWT>;
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createInitialJWTToken = createInitialJWTToken;
37
+ exports.getJWTFromCustomTokenCookie = getJWTFromCustomTokenCookie;
38
+ exports.handleJWTCallback = handleJWTCallback;
39
+ const jwt_1 = require("../core/jwt");
40
+ const license_1 = require("../utils/license");
41
+ /**
42
+ * JWT 콜백에서 초기 로그인 시 토큰 생성 헬퍼
43
+ */
44
+ function createInitialJWTToken(token, user, account) {
45
+ return {
46
+ ...token,
47
+ id: user.id,
48
+ email: user.email ?? undefined,
49
+ emailHash: user.emailHash ?? undefined,
50
+ maskedEmail: user.maskedEmail ?? undefined,
51
+ phoneHash: user.phoneHash ?? undefined,
52
+ maskedPhone: user.maskedPhone ?? undefined,
53
+ role: user.role,
54
+ phone: user.phone ?? undefined,
55
+ decryptedEmail: user.decryptedEmail ?? undefined,
56
+ decryptedPhone: user.decryptedPhone ?? undefined,
57
+ refreshToken: user.refreshToken ?? undefined,
58
+ accessTokenExpires: Date.now() + (15 * 60 * 1000),
59
+ serviceId: account?.serviceId ?? undefined,
60
+ };
61
+ }
62
+ /**
63
+ * 쿠키에서 커스텀 토큰을 읽어서 NextAuth JWT로 변환하는 헬퍼 함수
64
+ */
65
+ async function getJWTFromCustomTokenCookie(cookieName, secret, serviceId, licenseKey) {
66
+ try {
67
+ const { cookies } = await Promise.resolve().then(() => __importStar(require('next/headers')));
68
+ const cookieStore = await cookies();
69
+ const accessToken = cookieStore.get(cookieName)?.value;
70
+ if (!accessToken)
71
+ return null;
72
+ await (0, license_1.checkLicenseKey)(licenseKey);
73
+ const tokenResult = await (0, jwt_1.verifyToken)(accessToken, secret);
74
+ if (!tokenResult)
75
+ return null;
76
+ const { payload } = tokenResult;
77
+ const jwt = (0, jwt_1.createNextAuthJWT)(payload, serviceId);
78
+ jwt.accessTokenExpires = Date.now() + (15 * 60 * 1000);
79
+ const refreshTokenCookieName = cookieName.replace('_access_token', '_refresh_token');
80
+ const refreshToken = cookieStore.get(refreshTokenCookieName)?.value;
81
+ if (refreshToken) {
82
+ jwt.refreshToken = refreshToken;
83
+ }
84
+ return jwt;
85
+ }
86
+ catch (error) {
87
+ return null;
88
+ }
89
+ }
90
+ /**
91
+ * JWT 콜백을 위한 통합 헬퍼 함수
92
+ */
93
+ async function handleJWTCallback(token, user, account, options) {
94
+ const { secret, licenseKey, serviceId, cookieName, debug = false, ssoBaseURL, authServiceKey, } = options || {};
95
+ if (account && user) {
96
+ return createInitialJWTToken(token, user, account);
97
+ }
98
+ if (secret && licenseKey && serviceId) {
99
+ const cookieNameToUse = cookieName || `${serviceId}_access_token`;
100
+ const customJwt = await getJWTFromCustomTokenCookie(cookieNameToUse, secret, serviceId, licenseKey);
101
+ if (customJwt) {
102
+ if (token.refreshToken)
103
+ customJwt.refreshToken = token.refreshToken;
104
+ return customJwt;
105
+ }
106
+ }
107
+ const now = Date.now();
108
+ const expires = token.accessTokenExpires;
109
+ const hasValidToken = token.id && expires && expires > now;
110
+ const refreshToken = token.refreshToken;
111
+ if (hasValidToken)
112
+ return token;
113
+ if (refreshToken && ssoBaseURL && authServiceKey && secret) {
114
+ try {
115
+ const response = await fetch(`${ssoBaseURL}/api/sso/refresh`, {
116
+ method: 'POST',
117
+ headers: {
118
+ 'Content-Type': 'application/json',
119
+ 'x-auth-service-key': authServiceKey,
120
+ },
121
+ body: JSON.stringify({ refreshToken }),
122
+ });
123
+ if (response.ok) {
124
+ const result = await response.json();
125
+ if (result.success && result.accessToken) {
126
+ const tokenResult = await (0, jwt_1.verifyToken)(result.accessToken, secret);
127
+ if (tokenResult) {
128
+ const newJWT = (0, jwt_1.createNextAuthJWT)(tokenResult.payload, serviceId || '');
129
+ return {
130
+ ...newJWT,
131
+ refreshToken,
132
+ accessTokenExpires: Date.now() + (15 * 60 * 1000),
133
+ };
134
+ }
135
+ }
136
+ }
137
+ }
138
+ catch (error) {
139
+ console.error('[handleJWTCallback] Error refreshing token:', error);
140
+ }
141
+ }
142
+ return token;
143
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * NextAuth 쿠키 설정 생성
3
+ */
4
+ export declare function createNextAuthCookies(options: {
5
+ isProduction?: boolean;
6
+ cookieDomain?: string;
7
+ }): {
8
+ sessionToken: {
9
+ name: string;
10
+ options: {
11
+ httpOnly: boolean;
12
+ sameSite: 'lax' | 'none';
13
+ path: string;
14
+ secure: boolean;
15
+ domain?: string;
16
+ };
17
+ };
18
+ callbackUrl: {
19
+ name: string;
20
+ options: {
21
+ sameSite: 'lax' | 'none';
22
+ path: string;
23
+ secure: boolean;
24
+ domain?: string;
25
+ };
26
+ };
27
+ csrfToken: {
28
+ name: string;
29
+ options: {
30
+ httpOnly: boolean;
31
+ sameSite: 'lax' | 'none';
32
+ path: string;
33
+ secure: boolean;
34
+ domain?: string;
35
+ };
36
+ };
37
+ };
38
+ /**
39
+ * NextAuth 기본 설정 생성
40
+ */
41
+ export declare function createNextAuthBaseConfig(options: {
42
+ secret: string;
43
+ isProduction?: boolean;
44
+ cookieDomain?: string;
45
+ signInPath?: string;
46
+ errorPath?: string;
47
+ nextAuthUrl?: string;
48
+ sessionMaxAge?: number;
49
+ jwtMaxAge?: number;
50
+ }): any;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNextAuthCookies = createNextAuthCookies;
4
+ exports.createNextAuthBaseConfig = createNextAuthBaseConfig;
5
+ /**
6
+ * NextAuth 쿠키 설정 생성
7
+ */
8
+ function createNextAuthCookies(options) {
9
+ const { isProduction = false, cookieDomain } = options;
10
+ const isSecure = isProduction;
11
+ const sameSiteValue = cookieDomain ? 'lax' : (isSecure ? 'none' : 'lax');
12
+ return {
13
+ sessionToken: {
14
+ name: isSecure ? `__Secure-next-auth.session-token` : `next-auth.session-token`,
15
+ options: {
16
+ httpOnly: true,
17
+ sameSite: sameSiteValue,
18
+ path: '/',
19
+ secure: isSecure,
20
+ ...(cookieDomain && { domain: cookieDomain }),
21
+ },
22
+ },
23
+ callbackUrl: {
24
+ name: isSecure ? `__Secure-next-auth.callback-url` : `next-auth.callback-url`,
25
+ options: {
26
+ sameSite: sameSiteValue,
27
+ path: '/',
28
+ secure: isSecure,
29
+ ...(cookieDomain && { domain: cookieDomain }),
30
+ },
31
+ },
32
+ csrfToken: {
33
+ name: isSecure ? `__Secure-next-auth.csrf-token` : `next-auth.csrf-token`,
34
+ options: {
35
+ httpOnly: true,
36
+ sameSite: sameSiteValue,
37
+ path: '/',
38
+ secure: isSecure,
39
+ ...(cookieDomain && { domain: cookieDomain }),
40
+ },
41
+ },
42
+ };
43
+ }
44
+ /**
45
+ * NextAuth 기본 설정 생성
46
+ */
47
+ function createNextAuthBaseConfig(options) {
48
+ const { secret, isProduction = false, cookieDomain, signInPath = '/login', errorPath = '/login', nextAuthUrl, sessionMaxAge = 30 * 24 * 60 * 60, jwtMaxAge = 30 * 24 * 60 * 60, } = options;
49
+ return {
50
+ session: {
51
+ strategy: 'jwt',
52
+ maxAge: sessionMaxAge,
53
+ },
54
+ jwt: {
55
+ maxAge: jwtMaxAge,
56
+ },
57
+ providers: [],
58
+ ...(nextAuthUrl && { url: nextAuthUrl }),
59
+ pages: {
60
+ signIn: signInPath,
61
+ error: errorPath,
62
+ },
63
+ cookies: createNextAuthCookies({ isProduction, cookieDomain }),
64
+ secret,
65
+ };
66
+ }
@@ -0,0 +1,10 @@
1
+ import type { JWT } from "next-auth/jwt";
2
+ import type { Session } from "next-auth";
3
+ /**
4
+ * Session 콜백에서 빈 세션 반환 헬퍼
5
+ */
6
+ export declare function createEmptySession(session: Session): Session;
7
+ /**
8
+ * Session 콜백에서 토큰 정보를 세션에 매핑하는 헬퍼
9
+ */
10
+ export declare function mapTokenToSession(session: Session, token: JWT): Session;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createEmptySession = createEmptySession;
4
+ exports.mapTokenToSession = mapTokenToSession;
5
+ /**
6
+ * Session 콜백에서 빈 세션 반환 헬퍼
7
+ */
8
+ function createEmptySession(session) {
9
+ return {
10
+ ...session,
11
+ user: {
12
+ ...session.user,
13
+ id: '',
14
+ email: null,
15
+ role: 'GUEST',
16
+ },
17
+ expires: new Date().toISOString(),
18
+ };
19
+ }
20
+ /**
21
+ * Session 콜백에서 토큰 정보를 세션에 매핑하는 헬퍼
22
+ */
23
+ function mapTokenToSession(session, token) {
24
+ if (!session.user) {
25
+ return session;
26
+ }
27
+ const user = session.user;
28
+ user.id = token.id;
29
+ user.email = token.email;
30
+ user.name = token.name;
31
+ user.role = token.role;
32
+ user.smsVerified = token.smsVerified;
33
+ user.emailVerified = token.emailVerified;
34
+ user.phone = token.phone;
35
+ user.phoneVerified = token.phoneVerified;
36
+ user.isPasswordReset = token.isPasswordReset || false;
37
+ user.decryptedEmail = token.decryptedEmail;
38
+ user.decryptedPhone = token.decryptedPhone;
39
+ return session;
40
+ }
@@ -0,0 +1,23 @@
1
+ import type { ServiceInfo, SSORefreshTokenResponse } from '../types';
2
+ /**
3
+ * 서비스 구독 유효성 확인 함수
4
+ */
5
+ export declare function validateServiceSubscription(services: ServiceInfo[], serviceId: string, ssoBaseURL: string): {
6
+ isValid: boolean;
7
+ redirectUrl?: string;
8
+ service?: ServiceInfo;
9
+ };
10
+ /**
11
+ * SSO 서버에서 refresh token을 사용하여 새로운 access token을 발급받는 함수
12
+ */
13
+ export declare function refreshSSOToken(refreshToken: string, options: {
14
+ ssoBaseURL: string;
15
+ authServiceKey?: string;
16
+ }): Promise<SSORefreshTokenResponse>;
17
+ /**
18
+ * SSO 서버에서 사용자의 refresh token을 가져오는 함수
19
+ */
20
+ export declare function getRefreshTokenFromSSO(userId: string, accessToken: string, options: {
21
+ ssoBaseURL: string;
22
+ authServiceKey?: string;
23
+ }): Promise<string | null>;