@tern-secure/backend 1.0.0 → 1.1.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/.turbo/turbo-build.log +23 -23
- package/CHANGELOG.md +19 -0
- package/package.json +3 -5
- package/src/admin/sessionTernSecure.ts +118 -11
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
|
|
2
|
-
> @tern-secure/backend@1.
|
|
2
|
+
> @tern-secure/backend@1.1.0 build /home/runner/work/typescript/typescript/packages/backend
|
|
3
3
|
> pnpm clean && tsup && tsc -p tsconfig.add.json
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @tern-secure/backend@1.
|
|
6
|
+
> @tern-secure/backend@1.1.0 clean /home/runner/work/typescript/typescript/packages/backend
|
|
7
7
|
> rimraf dist
|
|
8
8
|
|
|
9
|
-
[34mCLI[39m Building entry: src/index.ts, src/ternsecureauth.ts, src/
|
|
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
10
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
11
11
|
[34mCLI[39m tsup v8.5.0
|
|
12
12
|
[34mCLI[39m Using tsup config: /home/runner/work/typescript/typescript/packages/backend/tsup.config.ts
|
|
@@ -17,32 +17,32 @@
|
|
|
17
17
|
[34mCLI[39m Target: node16
|
|
18
18
|
[34mCLI[39m Target: node16
|
|
19
19
|
[34mCLI[39m Cleaning output folder
|
|
20
|
-
[34mCJS[39m Build start
|
|
21
|
-
[34mCLI[39m Cleaning output folder
|
|
22
20
|
[34mESM[39m Build start
|
|
23
|
-
[
|
|
24
|
-
[
|
|
25
|
-
[
|
|
26
|
-
[32mCJS[39m [1mdist/cjs/ternsecureauth.js [22m[32m1.43 KB[39m
|
|
27
|
-
[32mCJS[39m [1mdist/cjs/admin/tenant.js [22m[32m2.25 KB[39m
|
|
28
|
-
[32mCJS[39m [1mdist/cjs/utils/config.js [22m[32m3.48 KB[39m
|
|
29
|
-
[32mCJS[39m [1mdist/cjs/admin/sessionTernSecure.js.map [22m[32m8.42 KB[39m
|
|
30
|
-
[32mCJS[39m [1mdist/cjs/index.js.map [22m[32m593.00 B[39m
|
|
31
|
-
[32mCJS[39m [1mdist/cjs/utils/admin-init.js.map [22m[32m1.42 KB[39m
|
|
32
|
-
[32mCJS[39m [1mdist/cjs/ternsecureauth.js.map [22m[32m885.00 B[39m
|
|
33
|
-
[32mCJS[39m [1mdist/cjs/admin/tenant.js.map [22m[32m2.46 KB[39m
|
|
34
|
-
[32mCJS[39m [1mdist/cjs/utils/config.js.map [22m[32m5.32 KB[39m
|
|
35
|
-
[32mCJS[39m ⚡️ Build success in 31ms
|
|
21
|
+
[34mCLI[39m Cleaning output folder
|
|
22
|
+
[34mCJS[39m Build start
|
|
23
|
+
[32mESM[39m [1mdist/esm/admin/sessionTernSecure.js [22m[32m6.87 KB[39m
|
|
36
24
|
[32mESM[39m [1mdist/esm/index.js [22m[32m593.00 B[39m
|
|
37
25
|
[32mESM[39m [1mdist/esm/utils/admin-init.js [22m[32m688.00 B[39m
|
|
38
|
-
[32mESM[39m [1mdist/esm/admin/sessionTernSecure.js [22m[32m3.92 KB[39m
|
|
39
26
|
[32mESM[39m [1mdist/esm/ternsecureauth.js [22m[32m407.00 B[39m
|
|
40
|
-
[32mESM[39m [1mdist/esm/utils/config.js [22m[32m2.26 KB[39m
|
|
41
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
|
|
42
30
|
[32mESM[39m [1mdist/esm/index.js.map [22m[32m593.00 B[39m
|
|
43
31
|
[32mESM[39m [1mdist/esm/utils/admin-init.js.map [22m[32m1.32 KB[39m
|
|
44
|
-
[32mESM[39m [1mdist/esm/admin/
|
|
32
|
+
[32mESM[39m [1mdist/esm/admin/tenant.js.map [22m[32m2.42 KB[39m
|
|
45
33
|
[32mESM[39m [1mdist/esm/ternsecureauth.js.map [22m[32m842.00 B[39m
|
|
46
34
|
[32mESM[39m [1mdist/esm/utils/config.js.map [22m[32m5.25 KB[39m
|
|
47
|
-
[32mESM[39m
|
|
48
|
-
[
|
|
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
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @tern-secure/backend
|
|
2
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
|
+
|
|
3
22
|
## 1.0.0
|
|
4
23
|
|
|
5
24
|
### Major Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tern-secure/backend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/TernSecure/typescript.git",
|
|
@@ -18,15 +18,13 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"tslib": "2.4.1",
|
|
21
|
-
"@tern-secure/types": "1.0.
|
|
21
|
+
"@tern-secure/types": "1.0.2"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
+
"firebase-admin": "^12.7.0",
|
|
24
25
|
"jose": "^5.0.0",
|
|
25
26
|
"next": "15.3.2"
|
|
26
27
|
},
|
|
27
|
-
"peerDependencies": {
|
|
28
|
-
"firebase-admin": "^12.0.0"
|
|
29
|
-
},
|
|
30
28
|
"engines": {
|
|
31
29
|
"node": ">=20"
|
|
32
30
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { cookies } from 'next/headers';
|
|
4
4
|
import { adminTernSecureAuth as adminAuth } from '../utils/admin-init';
|
|
5
|
-
import { handleFirebaseAuthError, type AuthErrorResponse } from '@tern-secure/types';
|
|
5
|
+
import { handleFirebaseAuthError, type AuthErrorResponse, type SessionParams, type SessionResult } from '@tern-secure/types';
|
|
6
6
|
|
|
7
7
|
interface FirebaseAuthError extends Error {
|
|
8
8
|
code?: string;
|
|
@@ -25,21 +25,128 @@ interface TernVerificationResult extends User {
|
|
|
25
25
|
error?: AuthErrorResponse
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
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> {
|
|
29
46
|
try {
|
|
30
|
-
|
|
31
|
-
|
|
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
|
+
}
|
|
32
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 {
|
|
33
107
|
const cookieStore = await cookies();
|
|
34
|
-
cookieStore.set(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
secure: process.env.NODE_ENV === 'production',
|
|
38
|
-
path: '/',
|
|
108
|
+
cookieStore.set(SESSION_CONSTANTS.COOKIE_NAME, sessionCookie, {
|
|
109
|
+
maxAge: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,
|
|
110
|
+
...COOKIE_OPTIONS,
|
|
39
111
|
});
|
|
40
|
-
|
|
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
|
+
|
|
41
141
|
} catch (error) {
|
|
42
|
-
|
|
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
|
+
};
|
|
43
150
|
}
|
|
44
151
|
}
|
|
45
152
|
|