@tern-secure/backend 1.1.0 → 1.1.2
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/cjs/admin/sessionTernSecure.js +256 -0
- package/dist/cjs/admin/sessionTernSecure.js.map +1 -0
- package/dist/cjs/admin/tenant.js +68 -0
- package/dist/cjs/admin/tenant.js.map +1 -0
- package/dist/cjs/index.js +48 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/ternsecureauth.js +40 -0
- package/dist/cjs/ternsecureauth.js.map +1 -0
- package/dist/cjs/utils/admin-init.js +60 -0
- package/dist/cjs/utils/admin-init.js.map +1 -0
- package/dist/cjs/utils/config.js +113 -0
- package/dist/cjs/utils/config.js.map +1 -0
- package/dist/esm/admin/sessionTernSecure.js +226 -0
- package/dist/esm/admin/sessionTernSecure.js.map +1 -0
- package/dist/esm/admin/tenant.js +43 -0
- package/dist/esm/admin/tenant.js.map +1 -0
- package/dist/esm/index.js +24 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/ternsecureauth.js +16 -0
- package/dist/esm/ternsecureauth.js.map +1 -0
- package/dist/esm/utils/admin-init.js +24 -0
- package/dist/esm/utils/admin-init.js.map +1 -0
- package/dist/esm/utils/config.js +84 -0
- package/dist/esm/utils/config.js.map +1 -0
- package/dist/types/admin/sessionTernSecure.d.ts +36 -0
- package/dist/types/admin/sessionTernSecure.d.ts.map +1 -0
- package/dist/types/admin/tenant.d.ts +17 -0
- package/dist/types/admin/tenant.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/ternsecureauth.d.ts +9 -0
- package/dist/types/ternsecureauth.d.ts.map +1 -0
- package/dist/types/utils/admin-init.d.ts +5 -0
- package/dist/types/utils/admin-init.d.ts.map +1 -0
- package/dist/types/utils/config.d.ts +35 -0
- package/dist/types/utils/config.d.ts.map +1 -0
- package/package.json +5 -2
- package/.turbo/turbo-build.log +0 -48
- package/CHANGELOG.md +0 -41
- package/src/admin/sessionTernSecure.ts +0 -300
- package/src/admin/tenant.ts +0 -63
- package/src/index.ts +0 -12
- package/src/ternsecureauth.ts +0 -18
- package/src/utils/admin-init.ts +0 -22
- package/src/utils/config.ts +0 -122
- package/tsconfig.add.json +0 -13
- package/tsconfig.json +0 -25
- package/tsup.config.ts +0 -31
package/.turbo/turbo-build.log
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @tern-secure/backend@1.1.0 build /home/runner/work/typescript/typescript/packages/backend
|
|
3
|
-
> pnpm clean && tsup && tsc -p tsconfig.add.json
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
> @tern-secure/backend@1.1.0 clean /home/runner/work/typescript/typescript/packages/backend
|
|
7
|
-
> rimraf dist
|
|
8
|
-
|
|
9
|
-
[34mCLI[39m Building entry: src/index.ts, src/ternsecureauth.ts, src/admin/sessionTernSecure.ts, src/admin/tenant.ts, src/utils/admin-init.ts, src/utils/config.ts
|
|
10
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
11
|
-
[34mCLI[39m tsup v8.5.0
|
|
12
|
-
[34mCLI[39m Using tsup config: /home/runner/work/typescript/typescript/packages/backend/tsup.config.ts
|
|
13
|
-
[34mCLI[39m Building entry: src/index.ts, src/ternsecureauth.ts, src/admin/sessionTernSecure.ts, src/admin/tenant.ts, src/utils/admin-init.ts, src/utils/config.ts
|
|
14
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
15
|
-
[34mCLI[39m tsup v8.5.0
|
|
16
|
-
[34mCLI[39m Using tsup config: /home/runner/work/typescript/typescript/packages/backend/tsup.config.ts
|
|
17
|
-
[34mCLI[39m Target: node16
|
|
18
|
-
[34mCLI[39m Target: node16
|
|
19
|
-
[34mCLI[39m Cleaning output folder
|
|
20
|
-
[34mESM[39m Build start
|
|
21
|
-
[34mCLI[39m Cleaning output folder
|
|
22
|
-
[34mCJS[39m Build start
|
|
23
|
-
[32mESM[39m [1mdist/esm/admin/sessionTernSecure.js [22m[32m6.87 KB[39m
|
|
24
|
-
[32mESM[39m [1mdist/esm/index.js [22m[32m593.00 B[39m
|
|
25
|
-
[32mESM[39m [1mdist/esm/utils/admin-init.js [22m[32m688.00 B[39m
|
|
26
|
-
[32mESM[39m [1mdist/esm/ternsecureauth.js [22m[32m407.00 B[39m
|
|
27
|
-
[32mESM[39m [1mdist/esm/admin/tenant.js [22m[32m1.19 KB[39m
|
|
28
|
-
[32mESM[39m [1mdist/esm/utils/config.js [22m[32m2.26 KB[39m
|
|
29
|
-
[32mESM[39m [1mdist/esm/admin/sessionTernSecure.js.map [22m[32m13.36 KB[39m
|
|
30
|
-
[32mESM[39m [1mdist/esm/index.js.map [22m[32m593.00 B[39m
|
|
31
|
-
[32mESM[39m [1mdist/esm/utils/admin-init.js.map [22m[32m1.32 KB[39m
|
|
32
|
-
[32mESM[39m [1mdist/esm/admin/tenant.js.map [22m[32m2.42 KB[39m
|
|
33
|
-
[32mESM[39m [1mdist/esm/ternsecureauth.js.map [22m[32m842.00 B[39m
|
|
34
|
-
[32mESM[39m [1mdist/esm/utils/config.js.map [22m[32m5.25 KB[39m
|
|
35
|
-
[32mESM[39m ⚡️ Build success in 34ms
|
|
36
|
-
[32mCJS[39m [1mdist/cjs/index.js [22m[32m2.01 KB[39m
|
|
37
|
-
[32mCJS[39m [1mdist/cjs/admin/tenant.js [22m[32m2.25 KB[39m
|
|
38
|
-
[32mCJS[39m [1mdist/cjs/utils/config.js [22m[32m3.48 KB[39m
|
|
39
|
-
[32mCJS[39m [1mdist/cjs/utils/admin-init.js [22m[32m2.55 KB[39m
|
|
40
|
-
[32mCJS[39m [1mdist/cjs/ternsecureauth.js [22m[32m1.43 KB[39m
|
|
41
|
-
[32mCJS[39m [1mdist/cjs/admin/sessionTernSecure.js [22m[32m8.57 KB[39m
|
|
42
|
-
[32mCJS[39m [1mdist/cjs/admin/tenant.js.map [22m[32m2.46 KB[39m
|
|
43
|
-
[32mCJS[39m [1mdist/cjs/utils/config.js.map [22m[32m5.32 KB[39m
|
|
44
|
-
[32mCJS[39m [1mdist/cjs/index.js.map [22m[32m593.00 B[39m
|
|
45
|
-
[32mCJS[39m [1mdist/cjs/utils/admin-init.js.map [22m[32m1.42 KB[39m
|
|
46
|
-
[32mCJS[39m [1mdist/cjs/ternsecureauth.js.map [22m[32m885.00 B[39m
|
|
47
|
-
[32mCJS[39m [1mdist/cjs/admin/sessionTernSecure.js.map [22m[32m13.49 KB[39m
|
|
48
|
-
[32mCJS[39m ⚡️ Build success in 34ms
|
package/CHANGELOG.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# @tern-secure/backend
|
|
2
|
-
|
|
3
|
-
## 1.1.0
|
|
4
|
-
|
|
5
|
-
### Minor Changes
|
|
6
|
-
|
|
7
|
-
- 5f29862: advanced Auth cookies and session management
|
|
8
|
-
|
|
9
|
-
### Patch Changes
|
|
10
|
-
|
|
11
|
-
- Updated dependencies [5f29862]
|
|
12
|
-
- @tern-secure/types@1.0.2
|
|
13
|
-
|
|
14
|
-
## 1.0.1
|
|
15
|
-
|
|
16
|
-
### Patch Changes
|
|
17
|
-
|
|
18
|
-
- 367a100: fix: Update ternUIgetScriptUrl to use TernSecureDev flag and switch CDN to HTTPS.
|
|
19
|
-
- Updated dependencies [367a100]
|
|
20
|
-
- @tern-secure/types@1.0.1
|
|
21
|
-
|
|
22
|
-
## 1.0.0
|
|
23
|
-
|
|
24
|
-
### Major Changes
|
|
25
|
-
|
|
26
|
-
- 2603f2b: Initial stable release of TernSecure Authentication SDK
|
|
27
|
-
|
|
28
|
-
This marks the first major release of the TernSecure Authentication monorepo, introducing a complete TypeScript SDK built on Firebase Authentication. The release includes:
|
|
29
|
-
|
|
30
|
-
- Core authentication utilities and types
|
|
31
|
-
- React hooks and components for seamless integration
|
|
32
|
-
- UI components library with form handling
|
|
33
|
-
- Backend utilities for server-side operations
|
|
34
|
-
- Comprehensive TypeScript support
|
|
35
|
-
|
|
36
|
-
All packages are now stable and ready for production use in React applications, Next.js projects, and general JavaScript/TypeScript environments.
|
|
37
|
-
|
|
38
|
-
### Patch Changes
|
|
39
|
-
|
|
40
|
-
- Updated dependencies [2603f2b]
|
|
41
|
-
- @tern-secure/types@1.0.0
|
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
'use server'
|
|
2
|
-
|
|
3
|
-
import { cookies } from 'next/headers';
|
|
4
|
-
import { adminTernSecureAuth as adminAuth } from '../utils/admin-init';
|
|
5
|
-
import { handleFirebaseAuthError, type AuthErrorResponse, type SessionParams, type SessionResult } from '@tern-secure/types';
|
|
6
|
-
|
|
7
|
-
interface FirebaseAuthError extends Error {
|
|
8
|
-
code?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface User {
|
|
12
|
-
uid: string | null;
|
|
13
|
-
email: string | null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface Session {
|
|
17
|
-
user: User | null;
|
|
18
|
-
token: string | null;
|
|
19
|
-
error: Error | null;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface TernVerificationResult extends User {
|
|
23
|
-
valid: boolean
|
|
24
|
-
authTime?: number
|
|
25
|
-
error?: AuthErrorResponse
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// DRY Constants
|
|
30
|
-
const SESSION_CONSTANTS = {
|
|
31
|
-
COOKIE_NAME: '_session_cookie',
|
|
32
|
-
DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1000, // 5 days
|
|
33
|
-
DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5,
|
|
34
|
-
} as const;
|
|
35
|
-
|
|
36
|
-
const COOKIE_OPTIONS = {
|
|
37
|
-
httpOnly: true,
|
|
38
|
-
secure: process.env.NODE_ENV === 'production',
|
|
39
|
-
sameSite: 'strict' as const,
|
|
40
|
-
path: '/',
|
|
41
|
-
} as const;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
export async function createSessionCookie(params: SessionParams | string): Promise<SessionResult> {
|
|
46
|
-
try {
|
|
47
|
-
// Handle both old string format and new object format for backward compatibility
|
|
48
|
-
const idToken = typeof params === 'string' ? params : params.idToken;
|
|
49
|
-
|
|
50
|
-
if (!idToken) {
|
|
51
|
-
const error = new Error('ID token is required for session creation');
|
|
52
|
-
console.error('[createSessionCookie] Missing ID token:', error);
|
|
53
|
-
return {
|
|
54
|
-
success: false,
|
|
55
|
-
message: 'ID token is required',
|
|
56
|
-
error: 'INVALID_TOKEN',
|
|
57
|
-
cookieSet: false
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Verify the ID token first
|
|
62
|
-
let decodedToken;
|
|
63
|
-
try {
|
|
64
|
-
decodedToken = await adminAuth.verifyIdToken(idToken);
|
|
65
|
-
} catch (verifyError) {
|
|
66
|
-
console.error('[createSessionCookie] ID token verification failed:', verifyError);
|
|
67
|
-
const authError = handleFirebaseAuthError(verifyError);
|
|
68
|
-
return {
|
|
69
|
-
success: false,
|
|
70
|
-
message: authError.message,
|
|
71
|
-
error: authError.code,
|
|
72
|
-
cookieSet: false
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!decodedToken) {
|
|
77
|
-
const error = new Error('Invalid ID token - verification returned null');
|
|
78
|
-
console.error('[createSessionCookie] Token verification returned null:', error);
|
|
79
|
-
return {
|
|
80
|
-
success: false,
|
|
81
|
-
message: 'Invalid ID token',
|
|
82
|
-
error: 'INVALID_TOKEN',
|
|
83
|
-
cookieSet: false
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Create session cookie
|
|
88
|
-
let sessionCookie;
|
|
89
|
-
try {
|
|
90
|
-
sessionCookie = await adminAuth.createSessionCookie(idToken, {
|
|
91
|
-
expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_MS
|
|
92
|
-
});
|
|
93
|
-
} catch (sessionError) {
|
|
94
|
-
console.error('[createSessionCookie] Firebase session cookie creation failed:', sessionError);
|
|
95
|
-
const authError = handleFirebaseAuthError(sessionError);
|
|
96
|
-
return {
|
|
97
|
-
success: false,
|
|
98
|
-
message: authError.message,
|
|
99
|
-
error: authError.code,
|
|
100
|
-
cookieSet: false
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Set the cookie and verify it was set
|
|
105
|
-
let cookieSetSuccessfully = false;
|
|
106
|
-
try {
|
|
107
|
-
const cookieStore = await cookies();
|
|
108
|
-
cookieStore.set(SESSION_CONSTANTS.COOKIE_NAME, sessionCookie, {
|
|
109
|
-
maxAge: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,
|
|
110
|
-
...COOKIE_OPTIONS,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// Verify the cookie was actually set
|
|
114
|
-
const verifySetCookie = cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);
|
|
115
|
-
cookieSetSuccessfully = !!verifySetCookie?.value;
|
|
116
|
-
|
|
117
|
-
if (!cookieSetSuccessfully) {
|
|
118
|
-
const error = new Error('Session cookie was not set successfully');
|
|
119
|
-
console.error('[createSessionCookie] Cookie verification failed:', error);
|
|
120
|
-
throw error;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
} catch (cookieError) {
|
|
124
|
-
console.error('[createSessionCookie] Failed to set session cookie:', cookieError);
|
|
125
|
-
return {
|
|
126
|
-
success: false,
|
|
127
|
-
message: 'Failed to set session cookie',
|
|
128
|
-
error: 'COOKIE_SET_FAILED',
|
|
129
|
-
cookieSet: false
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
console.log(`[createSessionCookie] Session cookie created successfully for user: ${decodedToken.uid}`);
|
|
134
|
-
return {
|
|
135
|
-
success: true,
|
|
136
|
-
message: 'Session created successfully',
|
|
137
|
-
expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,
|
|
138
|
-
cookieSet: cookieSetSuccessfully
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
} catch (error) {
|
|
142
|
-
console.error('[createSessionCookie] Unexpected error:', error);
|
|
143
|
-
const authError = handleFirebaseAuthError(error);
|
|
144
|
-
return {
|
|
145
|
-
success: false,
|
|
146
|
-
message: authError.message || 'Failed to create session',
|
|
147
|
-
error: authError.code || 'INTERNAL_ERROR',
|
|
148
|
-
cookieSet: false
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
export async function getServerSessionCookie() {
|
|
156
|
-
const cookieStore = await cookies();
|
|
157
|
-
const sessionCookie = cookieStore.get('_session_cookie')?.value;
|
|
158
|
-
|
|
159
|
-
if (!sessionCookie) {
|
|
160
|
-
throw new Error('No session cookie found')
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true)
|
|
165
|
-
return {
|
|
166
|
-
token: sessionCookie,
|
|
167
|
-
userId: decondeClaims.uid
|
|
168
|
-
}
|
|
169
|
-
} catch (error) {
|
|
170
|
-
console.error('Error verifying session:', error)
|
|
171
|
-
throw new Error('Invalid Session')
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
export async function getIdToken() {
|
|
177
|
-
const cookieStore = await cookies();
|
|
178
|
-
const token = cookieStore.get('_session_token')?.value;
|
|
179
|
-
|
|
180
|
-
if (!token) {
|
|
181
|
-
throw new Error('No session cookie found')
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
try {
|
|
185
|
-
const decodedClaims = await adminAuth.verifyIdToken(token)
|
|
186
|
-
return {
|
|
187
|
-
token: token,
|
|
188
|
-
userId: decodedClaims.uid
|
|
189
|
-
}
|
|
190
|
-
} catch (error) {
|
|
191
|
-
console.error('Error verifying session:', error)
|
|
192
|
-
throw new Error('Invalid Session')
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export async function setServerSession(token: string) {
|
|
197
|
-
try {
|
|
198
|
-
const cookieStore = await cookies();
|
|
199
|
-
cookieStore.set('_session_token', token, {
|
|
200
|
-
httpOnly: true,
|
|
201
|
-
secure: process.env.NODE_ENV === 'production',
|
|
202
|
-
sameSite: 'strict',
|
|
203
|
-
maxAge: 60 * 60, // 1 hour
|
|
204
|
-
path: '/',
|
|
205
|
-
});
|
|
206
|
-
return { success: true, message: 'Session created' };
|
|
207
|
-
} catch {
|
|
208
|
-
return { success: false, message: 'Failed to create session' };
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export async function verifyTernIdToken(token: string): Promise<TernVerificationResult> {
|
|
213
|
-
try {
|
|
214
|
-
const decodedToken = await adminAuth.verifyIdToken(token);
|
|
215
|
-
return {
|
|
216
|
-
valid: true,
|
|
217
|
-
uid: decodedToken.uid,
|
|
218
|
-
email: decodedToken.email || null,
|
|
219
|
-
authTime: decodedToken.auth_time
|
|
220
|
-
};
|
|
221
|
-
} catch (error) {
|
|
222
|
-
const errorResponse = handleFirebaseAuthError(error)
|
|
223
|
-
return {
|
|
224
|
-
valid: false,
|
|
225
|
-
uid: null,
|
|
226
|
-
email: null,
|
|
227
|
-
error: errorResponse
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
export async function verifyTernSessionCookie(session: string): Promise<TernVerificationResult>{
|
|
234
|
-
try {
|
|
235
|
-
const res = await adminAuth.verifySessionCookie(session);
|
|
236
|
-
return {
|
|
237
|
-
valid: true,
|
|
238
|
-
uid: res.uid,
|
|
239
|
-
email: res.email || null,
|
|
240
|
-
authTime: res.auth_time
|
|
241
|
-
};
|
|
242
|
-
} catch (error) {
|
|
243
|
-
const errorResponse = handleFirebaseAuthError(error)
|
|
244
|
-
return {
|
|
245
|
-
valid: false,
|
|
246
|
-
uid: null,
|
|
247
|
-
email: null,
|
|
248
|
-
error: errorResponse
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
export async function clearSessionCookie() {
|
|
255
|
-
const cookieStore = await cookies()
|
|
256
|
-
|
|
257
|
-
cookieStore.delete('_session_cookie')
|
|
258
|
-
cookieStore.delete('_session_token')
|
|
259
|
-
cookieStore.delete('_session')
|
|
260
|
-
|
|
261
|
-
try {
|
|
262
|
-
// Verify if there's an active session before revoking
|
|
263
|
-
const sessionCookie = cookieStore.get('_session_cookie')?.value
|
|
264
|
-
if (sessionCookie) {
|
|
265
|
-
// Get the decoded claims to get the user's ID
|
|
266
|
-
const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie)
|
|
267
|
-
|
|
268
|
-
// Revoke all sessions for the user
|
|
269
|
-
await adminAuth.revokeRefreshTokens(decodedClaims.uid)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return { success: true, message: 'Session cleared successfully' }
|
|
273
|
-
} catch (error) {
|
|
274
|
-
console.error('Error clearing session:', error)
|
|
275
|
-
// Still return success even if revoking fails, as cookies are cleared
|
|
276
|
-
return { success: true, message: 'Session cookies cleared' }
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
/*
|
|
283
|
-
export async function GET(request: NextRequest) {
|
|
284
|
-
const cookieStore = await cookies();
|
|
285
|
-
const sessionCookie = cookieStore.get('session')?.value
|
|
286
|
-
|
|
287
|
-
if (!sessionCookie) {
|
|
288
|
-
return NextResponse.json({ isAuthenticated: false }, { status: 401 })
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
try {
|
|
292
|
-
const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)
|
|
293
|
-
return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })
|
|
294
|
-
} catch (error) {
|
|
295
|
-
console.error('Error verifying session cookie:', error)
|
|
296
|
-
return NextResponse.json({ isAuthenticated: false }, { status: 401 })
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
*/
|
package/src/admin/tenant.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { TernSecureTenantManager } from "../utils/admin-init";
|
|
2
|
-
import type { SignInResponse } from '@tern-secure/types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export async function createTenant(
|
|
6
|
-
displayName: string,
|
|
7
|
-
emailSignInConfig: {
|
|
8
|
-
enabled: boolean;
|
|
9
|
-
passwordRequired: boolean;
|
|
10
|
-
},
|
|
11
|
-
multiFactorConfig?: {
|
|
12
|
-
state: 'ENABLED' | 'DISABLED';
|
|
13
|
-
factorIds: "phone"[];
|
|
14
|
-
testPhoneNumbers?: {
|
|
15
|
-
[phoneNumber: string]: string;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
) {
|
|
19
|
-
try {
|
|
20
|
-
const tenantConfig = {
|
|
21
|
-
displayName,
|
|
22
|
-
emailSignInConfig,
|
|
23
|
-
...(multiFactorConfig && { multiFactorConfig })
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const tenant = await TernSecureTenantManager.createTenant(tenantConfig);
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
success: true,
|
|
30
|
-
tenantId: tenant.tenantId,
|
|
31
|
-
displayName: tenant.displayName,
|
|
32
|
-
};
|
|
33
|
-
} catch (error) {
|
|
34
|
-
console.error('Error creating tenant:', error);
|
|
35
|
-
throw new Error('Failed to create tenant');
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function createTenantUser(
|
|
40
|
-
email: string,
|
|
41
|
-
password: string,
|
|
42
|
-
tenantId: string
|
|
43
|
-
): Promise<SignInResponse> {
|
|
44
|
-
try {
|
|
45
|
-
const tenantAuth = TernSecureTenantManager.authForTenant(tenantId);
|
|
46
|
-
|
|
47
|
-
const userRecord = await tenantAuth.createUser({
|
|
48
|
-
email,
|
|
49
|
-
password,
|
|
50
|
-
emailVerified: false,
|
|
51
|
-
disabled: false
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
success: true,
|
|
56
|
-
message: 'Tenant user created successfully',
|
|
57
|
-
user: userRecord.uid,
|
|
58
|
-
};
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.error('Error creating tenant user:', error);
|
|
61
|
-
throw new Error('Failed to create tenant user');
|
|
62
|
-
}
|
|
63
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
verifyTernSessionCookie,
|
|
3
|
-
createSessionCookie,
|
|
4
|
-
clearSessionCookie
|
|
5
|
-
} from './admin/sessionTernSecure'
|
|
6
|
-
export {
|
|
7
|
-
adminTernSecureAuth,
|
|
8
|
-
adminTernSecureDb,
|
|
9
|
-
TernSecureTenantManager
|
|
10
|
-
} from './utils/admin-init'
|
|
11
|
-
export { initializeAdminConfig } from './utils/config'
|
|
12
|
-
export { createTenant, createTenantUser } from './admin/tenant'
|
package/src/ternsecureauth.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Firebase implementation of the TernSecureAuthProvider interface
|
|
3
|
-
*/
|
|
4
|
-
export class TernSecureAuthProvider {
|
|
5
|
-
private static instance: TernSecureAuthProvider | null;
|
|
6
|
-
|
|
7
|
-
public static getOrCreateInstance(): TernSecureAuthProvider {
|
|
8
|
-
if (!TernSecureAuthProvider.instance) {
|
|
9
|
-
TernSecureAuthProvider.instance = new TernSecureAuthProvider();
|
|
10
|
-
}
|
|
11
|
-
return TernSecureAuthProvider.instance;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
static clearInstance() {
|
|
15
|
-
TernSecureAuthProvider.instance = null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
}
|
package/src/utils/admin-init.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import admin from 'firebase-admin';
|
|
2
|
-
import { initializeAdminConfig } from './config';
|
|
3
|
-
|
|
4
|
-
// Initialize Firebase Admin if not already initialized
|
|
5
|
-
if (!admin.apps.length) {
|
|
6
|
-
try {
|
|
7
|
-
const config = initializeAdminConfig();
|
|
8
|
-
admin.initializeApp({
|
|
9
|
-
credential: admin.credential.cert({
|
|
10
|
-
...config,
|
|
11
|
-
privateKey: config.privateKey.replace(/\\n/g, '\n'),
|
|
12
|
-
}),
|
|
13
|
-
});
|
|
14
|
-
} catch (error) {
|
|
15
|
-
console.error('Firebase admin initialization error', error);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Add explicit type annotations using the types from the admin namespace
|
|
20
|
-
export const adminTernSecureAuth: admin.auth.Auth = admin.auth();
|
|
21
|
-
export const adminTernSecureDb: admin.firestore.Firestore = admin.firestore();
|
|
22
|
-
export const TernSecureTenantManager: admin.auth.TenantManager = admin.auth().tenantManager();
|
package/src/utils/config.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TernSecureConfig,
|
|
3
|
-
ConfigValidationResult,
|
|
4
|
-
TernSecureAdminConfig,
|
|
5
|
-
AdminConfigValidationResult
|
|
6
|
-
} from '@tern-secure/types'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Loads Firebase configuration from environment variables
|
|
10
|
-
* @returns {TernSecureConfig} Firebase configuration object
|
|
11
|
-
*/
|
|
12
|
-
export const loadFireConfig = (): TernSecureConfig => ({
|
|
13
|
-
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '',
|
|
14
|
-
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '',
|
|
15
|
-
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || '',
|
|
16
|
-
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || '',
|
|
17
|
-
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || '',
|
|
18
|
-
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID || '',
|
|
19
|
-
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || undefined,
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Validates Firebase configuration
|
|
24
|
-
* @param {TernSecureConfig} config - Firebase configuration object
|
|
25
|
-
* @throws {Error} If required configuration values are missing
|
|
26
|
-
* @returns {TernSecureConfig} Validated configuration object
|
|
27
|
-
*/
|
|
28
|
-
export const validateConfig = (config: TernSecureConfig): ConfigValidationResult => {
|
|
29
|
-
const requiredFields: (keyof TernSecureConfig)[] = [
|
|
30
|
-
'apiKey',
|
|
31
|
-
'authDomain',
|
|
32
|
-
'projectId',
|
|
33
|
-
'storageBucket',
|
|
34
|
-
'messagingSenderId',
|
|
35
|
-
'appId'
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
const errors: string[] = []
|
|
39
|
-
|
|
40
|
-
requiredFields.forEach(field => {
|
|
41
|
-
if (!config[field]) {
|
|
42
|
-
errors.push(`Missing required field: NEXT_PUBLIC_FIREBASE_${String(field).toUpperCase()}`)
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
isValid: errors.length === 0,
|
|
48
|
-
errors,
|
|
49
|
-
config
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Initializes configuration with validation
|
|
55
|
-
* @throws {Error} If configuration is invalid
|
|
56
|
-
*/
|
|
57
|
-
export const initializeConfig = (): TernSecureConfig => {
|
|
58
|
-
const config = loadFireConfig()
|
|
59
|
-
const validationResult = validateConfig(config)
|
|
60
|
-
|
|
61
|
-
if (!validationResult.isValid) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`Firebase configuration validation failed:\n${validationResult.errors.join('\n')}`
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return config
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Loads Firebase Admin configuration from environment variables
|
|
72
|
-
* @returns {AdminConfig} Firebase Admin configuration object
|
|
73
|
-
*/
|
|
74
|
-
export const loadAdminConfig = (): TernSecureAdminConfig => ({
|
|
75
|
-
projectId: process.env.FIREBASE_PROJECT_ID || '',
|
|
76
|
-
clientEmail: process.env.FIREBASE_CLIENT_EMAIL || '',
|
|
77
|
-
privateKey: process.env.FIREBASE_PRIVATE_KEY || '',
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Validates Firebase Admin configuration
|
|
82
|
-
* @param {AdminConfig} config - Firebase Admin configuration object
|
|
83
|
-
* @returns {ConfigValidationResult} Validation result
|
|
84
|
-
*/
|
|
85
|
-
export const validateAdminConfig = (config: TernSecureAdminConfig): AdminConfigValidationResult => {
|
|
86
|
-
const requiredFields: (keyof TernSecureAdminConfig)[] = [
|
|
87
|
-
'projectId',
|
|
88
|
-
'clientEmail',
|
|
89
|
-
'privateKey'
|
|
90
|
-
]
|
|
91
|
-
|
|
92
|
-
const errors: string[] = []
|
|
93
|
-
|
|
94
|
-
requiredFields.forEach(field => {
|
|
95
|
-
if (!config[field]) {
|
|
96
|
-
errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`)
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
return {
|
|
101
|
-
isValid: errors.length === 0,
|
|
102
|
-
errors,
|
|
103
|
-
config
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Initializes admin configuration with validation
|
|
109
|
-
* @throws {Error} If configuration is invalid
|
|
110
|
-
*/
|
|
111
|
-
export const initializeAdminConfig = (): TernSecureAdminConfig => {
|
|
112
|
-
const config = loadAdminConfig()
|
|
113
|
-
const validationResult = validateAdminConfig(config)
|
|
114
|
-
|
|
115
|
-
if (!validationResult.isValid) {
|
|
116
|
-
throw new Error(
|
|
117
|
-
`Firebase Admin configuration validation failed:\n${validationResult.errors.join('\n')}`
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return config
|
|
122
|
-
}
|
package/tsconfig.add.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"declaration": true,
|
|
5
|
-
"declarationDir": "./dist/types",
|
|
6
|
-
"declarationMap": true,
|
|
7
|
-
"emitDeclarationOnly": true,
|
|
8
|
-
"noEmit": false,
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"sourceMap": false
|
|
11
|
-
},
|
|
12
|
-
"exclude": ["node_modules", "dist"]
|
|
13
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"allowJs": true,
|
|
4
|
-
"allowSyntheticDefaultImports": true,
|
|
5
|
-
"baseUrl": ".",
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"forceConsistentCasingInFileNames": true,
|
|
8
|
-
"importHelpers": true,
|
|
9
|
-
"isolatedModules": true,
|
|
10
|
-
"lib": ["es2020"],
|
|
11
|
-
"module": "NodeNext",
|
|
12
|
-
"moduleResolution": "nodenext",
|
|
13
|
-
"noImplicitReturns": true,
|
|
14
|
-
"noUnusedLocals": false,
|
|
15
|
-
"noUnusedParameters": false,
|
|
16
|
-
"outDir": "dist",
|
|
17
|
-
"resolveJsonModule": true,
|
|
18
|
-
"rootDir": "src",
|
|
19
|
-
"skipLibCheck": true,
|
|
20
|
-
"sourceMap": false,
|
|
21
|
-
"strict": true,
|
|
22
|
-
},
|
|
23
|
-
"include": ["src"],
|
|
24
|
-
"exclude": ["node_modules"]
|
|
25
|
-
}
|