@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.
- package/dist/core/auth-response.d.ts +15 -0
- package/dist/core/auth-response.js +45 -0
- package/dist/core/cookies.d.ts +33 -0
- package/dist/core/cookies.js +102 -0
- package/dist/core/jwt.d.ts +28 -0
- package/dist/core/jwt.js +180 -0
- package/dist/core/roles.d.ts +25 -0
- package/dist/core/roles.js +61 -0
- package/dist/core/verify.d.ts +40 -0
- package/dist/core/verify.js +181 -0
- package/dist/index.d.ts +18 -634
- package/dist/index.js +34 -1642
- package/dist/middleware/config.d.ts +15 -0
- package/dist/middleware/config.js +38 -0
- package/dist/middleware/handler.d.ts +6 -0
- package/dist/middleware/handler.js +228 -0
- package/dist/nextauth/callbacks.d.ts +35 -0
- package/dist/nextauth/callbacks.js +143 -0
- package/dist/nextauth/config.d.ts +50 -0
- package/dist/nextauth/config.js +66 -0
- package/dist/nextauth/session.d.ts +10 -0
- package/dist/nextauth/session.js +40 -0
- package/dist/sso/api.d.ts +23 -0
- package/dist/sso/api.js +83 -0
- package/dist/types/index.d.ts +138 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/crypto.d.ts +4 -0
- package/dist/utils/crypto.js +13 -0
- package/dist/utils/license.d.ts +4 -0
- package/dist/utils/license.js +20 -0
- package/dist/utils/logger.d.ts +5 -0
- package/dist/utils/logger.js +17 -0
- package/dist/utils/path.d.ts +12 -0
- package/dist/utils/path.js +25 -0
- package/dist/utils/redirect.d.ts +20 -0
- package/dist/utils/redirect.js +106 -0
- package/dist/utils/server.d.ts +15 -0
- package/dist/utils/server.js +42 -0
- package/package.json +2 -2
package/dist/sso/api.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateServiceSubscription = validateServiceSubscription;
|
|
4
|
+
exports.refreshSSOToken = refreshSSOToken;
|
|
5
|
+
exports.getRefreshTokenFromSSO = getRefreshTokenFromSSO;
|
|
6
|
+
/**
|
|
7
|
+
* 서비스 구독 유효성 확인 함수
|
|
8
|
+
*/
|
|
9
|
+
function validateServiceSubscription(services, serviceId, ssoBaseURL) {
|
|
10
|
+
const filteredServices = services.filter(service => service.serviceId === serviceId);
|
|
11
|
+
if (filteredServices.length === 0) {
|
|
12
|
+
return {
|
|
13
|
+
isValid: false,
|
|
14
|
+
redirectUrl: `${ssoBaseURL}/services/${serviceId}?type=subscription_required`
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const service = filteredServices[0];
|
|
18
|
+
if (service.isFree && service.status === "ACTIVE") {
|
|
19
|
+
return {
|
|
20
|
+
isValid: true,
|
|
21
|
+
service
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (service.status !== "ACTIVE") {
|
|
25
|
+
return {
|
|
26
|
+
isValid: false,
|
|
27
|
+
redirectUrl: `${ssoBaseURL}/services/${service.serviceId}?type=subscription_required`,
|
|
28
|
+
service
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
isValid: true,
|
|
33
|
+
service
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* SSO 서버에서 refresh token을 사용하여 새로운 access token을 발급받는 함수
|
|
38
|
+
*/
|
|
39
|
+
async function refreshSSOToken(refreshToken, options) {
|
|
40
|
+
const { ssoBaseURL, authServiceKey } = options;
|
|
41
|
+
if (!authServiceKey) {
|
|
42
|
+
throw new Error('AUTH_SERVICE_SECRET_KEY not configured');
|
|
43
|
+
}
|
|
44
|
+
const refreshResponse = await fetch(`${ssoBaseURL}/api/sso/refresh`, {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: {
|
|
47
|
+
'Content-Type': 'application/json',
|
|
48
|
+
'x-auth-service-key': authServiceKey,
|
|
49
|
+
},
|
|
50
|
+
body: JSON.stringify({ refreshToken }),
|
|
51
|
+
});
|
|
52
|
+
return await refreshResponse.json();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* SSO 서버에서 사용자의 refresh token을 가져오는 함수
|
|
56
|
+
*/
|
|
57
|
+
async function getRefreshTokenFromSSO(userId, accessToken, options) {
|
|
58
|
+
const { ssoBaseURL, authServiceKey } = options;
|
|
59
|
+
if (!authServiceKey) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const refreshResponse = await fetch(`${ssoBaseURL}/api/sso/get-refresh-token`, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
'x-auth-service-key': authServiceKey,
|
|
68
|
+
},
|
|
69
|
+
body: JSON.stringify({
|
|
70
|
+
userId,
|
|
71
|
+
accessToken
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
const refreshResult = await refreshResponse.json();
|
|
75
|
+
if (refreshResponse.ok && refreshResult.success && refreshResult.refreshToken) {
|
|
76
|
+
return refreshResult.refreshToken;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Ignore error
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
export interface ResponseLike {
|
|
2
|
+
cookies: {
|
|
3
|
+
delete(name: string): void;
|
|
4
|
+
set(name: string, value: string, options?: {
|
|
5
|
+
httpOnly?: boolean;
|
|
6
|
+
secure?: boolean;
|
|
7
|
+
sameSite?: 'strict' | 'lax' | 'none';
|
|
8
|
+
maxAge?: number;
|
|
9
|
+
path?: string;
|
|
10
|
+
domain?: string;
|
|
11
|
+
}): void;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface ServiceInfo {
|
|
15
|
+
serviceId: string;
|
|
16
|
+
role: string;
|
|
17
|
+
joinedAt: string;
|
|
18
|
+
lastAccessAt?: string;
|
|
19
|
+
expiredAt?: string;
|
|
20
|
+
status: string;
|
|
21
|
+
isFree?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface SSOUpsertResponse {
|
|
24
|
+
success: boolean;
|
|
25
|
+
message?: string;
|
|
26
|
+
user?: {
|
|
27
|
+
id: string;
|
|
28
|
+
email: string;
|
|
29
|
+
name: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface SSOErrorResponse {
|
|
33
|
+
error: string;
|
|
34
|
+
message?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface SSORefreshTokenResponse {
|
|
37
|
+
success: boolean;
|
|
38
|
+
accessToken?: string;
|
|
39
|
+
refreshToken?: string;
|
|
40
|
+
user?: {
|
|
41
|
+
id: string;
|
|
42
|
+
email: string;
|
|
43
|
+
name: string;
|
|
44
|
+
};
|
|
45
|
+
error?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface SSOGetRefreshTokenResponse {
|
|
48
|
+
success: boolean;
|
|
49
|
+
refreshToken?: string;
|
|
50
|
+
error?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface SSORegisterResponse {
|
|
53
|
+
success: boolean;
|
|
54
|
+
message?: string;
|
|
55
|
+
user?: {
|
|
56
|
+
id: string;
|
|
57
|
+
email: string;
|
|
58
|
+
name: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export interface JWTPayload {
|
|
62
|
+
sub?: string;
|
|
63
|
+
id?: string;
|
|
64
|
+
email: string;
|
|
65
|
+
name: string;
|
|
66
|
+
role?: string;
|
|
67
|
+
iat?: number;
|
|
68
|
+
exp?: number;
|
|
69
|
+
services?: ServiceInfo[];
|
|
70
|
+
phoneVerified?: boolean;
|
|
71
|
+
emailVerified?: boolean;
|
|
72
|
+
smsVerified?: boolean;
|
|
73
|
+
phone?: string;
|
|
74
|
+
isPasswordReset?: boolean;
|
|
75
|
+
decryptedEmail?: string;
|
|
76
|
+
decryptedPhone?: string;
|
|
77
|
+
emailHash?: string;
|
|
78
|
+
maskedEmail?: string;
|
|
79
|
+
phoneHash?: string;
|
|
80
|
+
maskedPhone?: string;
|
|
81
|
+
refreshToken?: string;
|
|
82
|
+
accessToken?: string;
|
|
83
|
+
accessTokenExpires?: number;
|
|
84
|
+
serviceId?: string;
|
|
85
|
+
[key: string]: unknown;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 역할 기반 접근 제어 헬퍼 함수
|
|
89
|
+
*/
|
|
90
|
+
export interface RoleAccessConfig {
|
|
91
|
+
[role: string]: {
|
|
92
|
+
paths: string[];
|
|
93
|
+
message: string;
|
|
94
|
+
allowedRoles?: string[];
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 미들웨어 설정 인터페이스
|
|
99
|
+
*/
|
|
100
|
+
export interface MiddlewareConfig {
|
|
101
|
+
/** 공개 접근 가능한 경로 배열 */
|
|
102
|
+
publicPaths?: string[];
|
|
103
|
+
/** 구독이 필요한 경로 배열 */
|
|
104
|
+
subscriptionRequiredPaths?: string[];
|
|
105
|
+
/** 구독 상태 확인을 제외할 API 경로 배열 */
|
|
106
|
+
subscriptionExemptApiPaths?: string[];
|
|
107
|
+
/** 인증 관련 API 경로 배열 */
|
|
108
|
+
authApiPaths?: string[];
|
|
109
|
+
/** 역할별 대시보드 경로 객체 */
|
|
110
|
+
rolePaths?: Record<string, string>;
|
|
111
|
+
/** 역할 기반 접근 제어 설정 */
|
|
112
|
+
roleAccessConfig?: RoleAccessConfig;
|
|
113
|
+
/** 서비스 ID */
|
|
114
|
+
serviceId?: string;
|
|
115
|
+
/** 시스템 관리자 역할명 (기본값: 'SYSTEM_ADMIN') */
|
|
116
|
+
systemAdminRole?: string;
|
|
117
|
+
/** 에러 페이지 경로 (기본값: '/error') */
|
|
118
|
+
errorPath?: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 미들웨어 실행 옵션
|
|
122
|
+
*/
|
|
123
|
+
export interface MiddlewareOptions {
|
|
124
|
+
/** NextAuth Secret (필수) */
|
|
125
|
+
secret: string;
|
|
126
|
+
/** 프로덕션 환경 여부 (필수) */
|
|
127
|
+
isProduction: boolean;
|
|
128
|
+
/** 쿠키 도메인 (선택사항) */
|
|
129
|
+
cookieDomain?: string;
|
|
130
|
+
/** NextAuth 토큰을 가져오는 함수 (선택사항) */
|
|
131
|
+
getNextAuthToken?: (req: any) => Promise<any>;
|
|
132
|
+
/** SSO 서버 기본 URL (필수) */
|
|
133
|
+
ssoBaseURL: string;
|
|
134
|
+
/** 인증 서비스 키 (선택사항) */
|
|
135
|
+
authServiceKey?: string;
|
|
136
|
+
/** 라이센스 키 (필수) */
|
|
137
|
+
licenseKey: string;
|
|
138
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createHashSHA256 = createHashSHA256;
|
|
4
|
+
/**
|
|
5
|
+
* Edge Runtime 호환을 위해 Web Crypto API 사용
|
|
6
|
+
*/
|
|
7
|
+
async function createHashSHA256(data) {
|
|
8
|
+
const encoder = new TextEncoder();
|
|
9
|
+
const dataBuffer = encoder.encode(data);
|
|
10
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
|
|
11
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
12
|
+
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkLicenseKey = checkLicenseKey;
|
|
4
|
+
const crypto_1 = require("./crypto");
|
|
5
|
+
// 유효한 라이센스 키 해시 목록
|
|
6
|
+
const VALID_LICENSE_KEY_HASHES = new Set([
|
|
7
|
+
'73bce4f3b64804c255cdab450d759a8b53038f9edb59ae42d9988b08dfd007e2',
|
|
8
|
+
]);
|
|
9
|
+
/**
|
|
10
|
+
* 라이센스 키 유효성 확인
|
|
11
|
+
*/
|
|
12
|
+
async function checkLicenseKey(licenseKey) {
|
|
13
|
+
if (!licenseKey || licenseKey.length < 10) {
|
|
14
|
+
throw new Error('License key is required');
|
|
15
|
+
}
|
|
16
|
+
const keyHash = await (0, crypto_1.createHashSHA256)(licenseKey);
|
|
17
|
+
if (!VALID_LICENSE_KEY_HASHES.has(keyHash)) {
|
|
18
|
+
throw new Error('Invalid license key');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.debugLog = debugLog;
|
|
4
|
+
exports.debugError = debugError;
|
|
5
|
+
/**
|
|
6
|
+
* 조건부 로깅 유틸리티 (환경 변수 AUTH_UTILS_DEBUG=true 시에만 로그 출력)
|
|
7
|
+
*/
|
|
8
|
+
function debugLog(context, ...args) {
|
|
9
|
+
if (process.env.AUTH_UTILS_DEBUG === 'true' || process.env.NODE_ENV === 'development') {
|
|
10
|
+
console.log(`[${context}]`, ...args);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function debugError(context, ...args) {
|
|
14
|
+
if (process.env.AUTH_UTILS_DEBUG === 'true' || process.env.NODE_ENV === 'development') {
|
|
15
|
+
console.error(`[${context}]`, ...args);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 공개 경로인지 확인하는 함수
|
|
3
|
+
*/
|
|
4
|
+
export declare function isPublicPath(pathname: string, publicPaths: string[]): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* API 경로인지 확인하는 함수
|
|
7
|
+
*/
|
|
8
|
+
export declare function isApiPath(pathname: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* 보호된 API 경로인지 확인하는 함수
|
|
11
|
+
*/
|
|
12
|
+
export declare function isProtectedApiPath(pathname: string, exemptPaths?: string[]): boolean;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPublicPath = isPublicPath;
|
|
4
|
+
exports.isApiPath = isApiPath;
|
|
5
|
+
exports.isProtectedApiPath = isProtectedApiPath;
|
|
6
|
+
/**
|
|
7
|
+
* 공개 경로인지 확인하는 함수
|
|
8
|
+
*/
|
|
9
|
+
function isPublicPath(pathname, publicPaths) {
|
|
10
|
+
return publicPaths.some(path => pathname === path || pathname.startsWith(path));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* API 경로인지 확인하는 함수
|
|
14
|
+
*/
|
|
15
|
+
function isApiPath(pathname) {
|
|
16
|
+
return pathname.startsWith('/api/');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 보호된 API 경로인지 확인하는 함수
|
|
20
|
+
*/
|
|
21
|
+
function isProtectedApiPath(pathname, exemptPaths = []) {
|
|
22
|
+
if (!isApiPath(pathname))
|
|
23
|
+
return false;
|
|
24
|
+
return !exemptPaths.some(path => pathname.startsWith(path));
|
|
25
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
/**
|
|
3
|
+
* 리다이렉트용 HTML 생성
|
|
4
|
+
* @param redirectPath 리다이렉트할 경로
|
|
5
|
+
* @param text 표시할 텍스트 (필수)
|
|
6
|
+
* @returns HTML 문자열
|
|
7
|
+
*/
|
|
8
|
+
export declare function createRedirectHTML(redirectPath: string, text: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* 에러 페이지로 리다이렉트하는 헬퍼 함수
|
|
11
|
+
*/
|
|
12
|
+
export declare function redirectToError(req: NextRequest, code: string, message: string, errorPath?: string): Promise<NextResponse>;
|
|
13
|
+
/**
|
|
14
|
+
* SSO 로그인 페이지로 리다이렉트하는 헬퍼 함수
|
|
15
|
+
*/
|
|
16
|
+
export declare function redirectToSSOLogin(req: NextRequest, serviceId: string, ssoBaseURL: string): Promise<NextResponse>;
|
|
17
|
+
/**
|
|
18
|
+
* 역할별 대시보드 경로로 리다이렉트하는 헬퍼 함수
|
|
19
|
+
*/
|
|
20
|
+
export declare function redirectToRoleDashboard(req: NextRequest, role: string, rolePaths: Record<string, string>, defaultPath?: string): Promise<NextResponse>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRedirectHTML = createRedirectHTML;
|
|
4
|
+
exports.redirectToError = redirectToError;
|
|
5
|
+
exports.redirectToSSOLogin = redirectToSSOLogin;
|
|
6
|
+
exports.redirectToRoleDashboard = redirectToRoleDashboard;
|
|
7
|
+
const server_1 = require("./server");
|
|
8
|
+
/**
|
|
9
|
+
* 리다이렉트용 HTML 생성
|
|
10
|
+
* @param redirectPath 리다이렉트할 경로
|
|
11
|
+
* @param text 표시할 텍스트 (필수)
|
|
12
|
+
* @returns HTML 문자열
|
|
13
|
+
*/
|
|
14
|
+
function createRedirectHTML(redirectPath, text) {
|
|
15
|
+
return `
|
|
16
|
+
<!DOCTYPE html>
|
|
17
|
+
<html>
|
|
18
|
+
<head>
|
|
19
|
+
<meta charset="utf-8">
|
|
20
|
+
<title>Redirecting...</title>
|
|
21
|
+
<style>
|
|
22
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
23
|
+
html, body {
|
|
24
|
+
width: 100%;
|
|
25
|
+
height: 100%;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
}
|
|
28
|
+
body {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: flex-start;
|
|
31
|
+
justify-content: flex-start;
|
|
32
|
+
padding-left: 10%;
|
|
33
|
+
padding-top: 20%;
|
|
34
|
+
background: #fff;
|
|
35
|
+
}
|
|
36
|
+
.typing-text {
|
|
37
|
+
font-family: 'Courier New', monospace;
|
|
38
|
+
font-size: 2.5rem;
|
|
39
|
+
font-weight: bold;
|
|
40
|
+
color: #667eea;
|
|
41
|
+
letter-spacing: 0.1em;
|
|
42
|
+
}
|
|
43
|
+
.cursor {
|
|
44
|
+
display: inline-block;
|
|
45
|
+
width: 3px;
|
|
46
|
+
height: 2.5rem;
|
|
47
|
+
background-color: #667eea;
|
|
48
|
+
margin-left: 2px;
|
|
49
|
+
animation: blink 0.7s infinite;
|
|
50
|
+
}
|
|
51
|
+
@keyframes blink {
|
|
52
|
+
0%, 50% { opacity: 1; }
|
|
53
|
+
51%, 100% { opacity: 0; }
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
<div class="typing-text">
|
|
59
|
+
<span id="text"></span><span class="cursor"></span>
|
|
60
|
+
</div>
|
|
61
|
+
<script>
|
|
62
|
+
const text = '${text}';
|
|
63
|
+
let index = 0;
|
|
64
|
+
const speed = 100;
|
|
65
|
+
|
|
66
|
+
function type() {
|
|
67
|
+
if (index < text.length) {
|
|
68
|
+
document.getElementById('text').textContent += text.charAt(index);
|
|
69
|
+
index++;
|
|
70
|
+
setTimeout(type, speed);
|
|
71
|
+
} else {
|
|
72
|
+
setTimeout(() => window.location.href = '${redirectPath}', 200);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
type();
|
|
77
|
+
</script>
|
|
78
|
+
</body>
|
|
79
|
+
</html>
|
|
80
|
+
`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 에러 페이지로 리다이렉트하는 헬퍼 함수
|
|
84
|
+
*/
|
|
85
|
+
async function redirectToError(req, code, message, errorPath = '/error') {
|
|
86
|
+
const url = new URL(errorPath, req.url);
|
|
87
|
+
url.searchParams.set('code', code);
|
|
88
|
+
url.searchParams.set('message', message);
|
|
89
|
+
const { NextResponse: NextResponseClass } = await (0, server_1.getNextServer)();
|
|
90
|
+
return NextResponseClass.redirect(url);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* SSO 로그인 페이지로 리다이렉트하는 헬퍼 함수
|
|
94
|
+
*/
|
|
95
|
+
async function redirectToSSOLogin(req, serviceId, ssoBaseURL) {
|
|
96
|
+
const { NextResponse: NextResponseClass } = await (0, server_1.getNextServer)();
|
|
97
|
+
return NextResponseClass.redirect(new URL(`${ssoBaseURL}/auth/login?serviceId=${serviceId}`, req.url));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 역할별 대시보드 경로로 리다이렉트하는 헬퍼 함수
|
|
101
|
+
*/
|
|
102
|
+
async function redirectToRoleDashboard(req, role, rolePaths, defaultPath = '/admin') {
|
|
103
|
+
const redirectPath = rolePaths[role] || defaultPath;
|
|
104
|
+
const { NextResponse: NextResponseClass } = await (0, server_1.getNextServer)();
|
|
105
|
+
return NextResponseClass.redirect(new URL(redirectPath, req.url));
|
|
106
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge Runtime 호환을 위해 next/server를 동적 import
|
|
3
|
+
*/
|
|
4
|
+
export declare function getNextServer(): Promise<{
|
|
5
|
+
default: typeof import("next/server");
|
|
6
|
+
NextFetchEvent: typeof import("next/server").NextFetchEvent;
|
|
7
|
+
NextRequest: typeof import("next/server").NextRequest;
|
|
8
|
+
NextResponse: typeof import("next/server").NextResponse;
|
|
9
|
+
userAgentFromString: typeof import("next/server").userAgentFromString;
|
|
10
|
+
userAgent: typeof import("next/server").userAgent;
|
|
11
|
+
URLPattern: typeof import("next/server").URLPattern;
|
|
12
|
+
ImageResponse: typeof import("next/server").ImageResponse;
|
|
13
|
+
after: typeof import("next/server").after;
|
|
14
|
+
connection: typeof import("next/server").connection;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,42 @@
|
|
|
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.getNextServer = getNextServer;
|
|
37
|
+
/**
|
|
38
|
+
* Edge Runtime 호환을 위해 next/server를 동적 import
|
|
39
|
+
*/
|
|
40
|
+
async function getNextServer() {
|
|
41
|
+
return await Promise.resolve().then(() => __importStar(require('next/server')));
|
|
42
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thinkingcat/auth-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Authentication utilities for ThinkingCat SSO services with conditional logging",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -40,4 +40,4 @@
|
|
|
40
40
|
"README.md",
|
|
41
41
|
".env.example"
|
|
42
42
|
]
|
|
43
|
-
}
|
|
43
|
+
}
|