@tern-secure/nextjs 4.0.0 → 4.2.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.
Files changed (132) hide show
  1. package/dist/cjs/app-router/client/TernSecureProvider.js +17 -2
  2. package/dist/cjs/app-router/client/TernSecureProvider.js.map +1 -1
  3. package/dist/cjs/app-router/client/actions.js +49 -49
  4. package/dist/cjs/app-router/client/actions.js.map +1 -1
  5. package/dist/cjs/app-router/route-handler/internal-route.js +17 -2
  6. package/dist/cjs/app-router/route-handler/internal-route.js.map +1 -1
  7. package/dist/cjs/app-router/server/auth.js +42 -28
  8. package/dist/cjs/app-router/server/auth.js.map +1 -1
  9. package/dist/cjs/app-router/server/edge-session.js +80 -0
  10. package/dist/cjs/app-router/server/edge-session.js.map +1 -0
  11. package/dist/cjs/app-router/server/index.js +4 -0
  12. package/dist/cjs/app-router/server/index.js.map +1 -1
  13. package/dist/cjs/app-router/server/jwt.js +141 -0
  14. package/dist/cjs/app-router/server/jwt.js.map +1 -0
  15. package/dist/cjs/app-router/server/sessionTernSecure.js +14 -9
  16. package/dist/cjs/app-router/server/sessionTernSecure.js.map +1 -1
  17. package/dist/cjs/app-router/server/ternSecureMiddleware.js +134 -13
  18. package/dist/cjs/app-router/server/ternSecureMiddleware.js.map +1 -1
  19. package/dist/cjs/boundary/TernSecureClientProvider.js +163 -40
  20. package/dist/cjs/boundary/TernSecureClientProvider.js.map +1 -1
  21. package/dist/cjs/boundary/TernSecureCtx.js.map +1 -1
  22. package/dist/cjs/boundary/hooks/useAuth.js +7 -8
  23. package/dist/cjs/boundary/hooks/useAuth.js.map +1 -1
  24. package/dist/cjs/components/sign-in.js +136 -45
  25. package/dist/cjs/components/sign-in.js.map +1 -1
  26. package/dist/cjs/components/sign-out-button.js +10 -1
  27. package/dist/cjs/components/sign-out-button.js.map +1 -1
  28. package/dist/cjs/components/sign-out.js +12 -3
  29. package/dist/cjs/components/sign-out.js.map +1 -1
  30. package/dist/cjs/components/sign-up.js +10 -5
  31. package/dist/cjs/components/sign-up.js.map +1 -1
  32. package/dist/cjs/errors.js +232 -5
  33. package/dist/cjs/errors.js.map +1 -1
  34. package/dist/cjs/index.js +0 -3
  35. package/dist/cjs/index.js.map +1 -1
  36. package/dist/cjs/types.js +14 -0
  37. package/dist/cjs/types.js.map +1 -1
  38. package/dist/cjs/utils/construct.js +50 -18
  39. package/dist/cjs/utils/construct.js.map +1 -1
  40. package/dist/cjs/utils/redirect.js +57 -0
  41. package/dist/cjs/utils/redirect.js.map +1 -0
  42. package/dist/esm/app-router/client/TernSecureProvider.js +17 -2
  43. package/dist/esm/app-router/client/TernSecureProvider.js.map +1 -1
  44. package/dist/esm/app-router/client/actions.js +59 -51
  45. package/dist/esm/app-router/client/actions.js.map +1 -1
  46. package/dist/esm/app-router/route-handler/internal-route.js +13 -1
  47. package/dist/esm/app-router/route-handler/internal-route.js.map +1 -1
  48. package/dist/esm/app-router/server/auth.js +40 -28
  49. package/dist/esm/app-router/server/auth.js.map +1 -1
  50. package/dist/esm/app-router/server/edge-session.js +56 -0
  51. package/dist/esm/app-router/server/edge-session.js.map +1 -0
  52. package/dist/esm/app-router/server/index.js +4 -2
  53. package/dist/esm/app-router/server/index.js.map +1 -1
  54. package/dist/esm/app-router/server/jwt.js +117 -0
  55. package/dist/esm/app-router/server/jwt.js.map +1 -0
  56. package/dist/esm/app-router/server/sessionTernSecure.js +14 -9
  57. package/dist/esm/app-router/server/sessionTernSecure.js.map +1 -1
  58. package/dist/esm/app-router/server/ternSecureMiddleware.js +132 -13
  59. package/dist/esm/app-router/server/ternSecureMiddleware.js.map +1 -1
  60. package/dist/esm/boundary/TernSecureClientProvider.js +164 -41
  61. package/dist/esm/boundary/TernSecureClientProvider.js.map +1 -1
  62. package/dist/esm/boundary/TernSecureCtx.js.map +1 -1
  63. package/dist/esm/boundary/hooks/useAuth.js +7 -8
  64. package/dist/esm/boundary/hooks/useAuth.js.map +1 -1
  65. package/dist/esm/components/sign-in.js +137 -46
  66. package/dist/esm/components/sign-in.js.map +1 -1
  67. package/dist/esm/components/sign-out-button.js +11 -2
  68. package/dist/esm/components/sign-out-button.js.map +1 -1
  69. package/dist/esm/components/sign-out.js +13 -4
  70. package/dist/esm/components/sign-out.js.map +1 -1
  71. package/dist/esm/components/sign-up.js +10 -5
  72. package/dist/esm/components/sign-up.js.map +1 -1
  73. package/dist/esm/errors.js +228 -4
  74. package/dist/esm/errors.js.map +1 -1
  75. package/dist/esm/index.js +0 -2
  76. package/dist/esm/index.js.map +1 -1
  77. package/dist/esm/types.js +6 -0
  78. package/dist/esm/types.js.map +1 -1
  79. package/dist/esm/utils/construct.js +46 -17
  80. package/dist/esm/utils/construct.js.map +1 -1
  81. package/dist/esm/utils/redirect.js +32 -0
  82. package/dist/esm/utils/redirect.js.map +1 -0
  83. package/dist/types/app-router/client/TernSecureProvider.d.ts +14 -3
  84. package/dist/types/app-router/client/TernSecureProvider.d.ts.map +1 -1
  85. package/dist/types/app-router/client/actions.d.ts +23 -21
  86. package/dist/types/app-router/client/actions.d.ts.map +1 -1
  87. package/dist/types/app-router/route-handler/internal-route.d.ts +3 -0
  88. package/dist/types/app-router/route-handler/internal-route.d.ts.map +1 -1
  89. package/dist/types/app-router/server/auth.d.ts +13 -1
  90. package/dist/types/app-router/server/auth.d.ts.map +1 -1
  91. package/dist/types/app-router/server/edge-session.d.ts +15 -0
  92. package/dist/types/app-router/server/edge-session.d.ts.map +1 -0
  93. package/dist/types/app-router/server/index.d.ts +3 -2
  94. package/dist/types/app-router/server/index.d.ts.map +1 -1
  95. package/dist/types/app-router/server/jwt.d.ts +20 -0
  96. package/dist/types/app-router/server/jwt.d.ts.map +1 -0
  97. package/dist/types/app-router/server/sessionTernSecure.d.ts +4 -1
  98. package/dist/types/app-router/server/sessionTernSecure.d.ts.map +1 -1
  99. package/dist/types/app-router/server/ternSecureMiddleware.d.ts +17 -4
  100. package/dist/types/app-router/server/ternSecureMiddleware.d.ts.map +1 -1
  101. package/dist/types/boundary/TernSecureClientProvider.d.ts +17 -1
  102. package/dist/types/boundary/TernSecureClientProvider.d.ts.map +1 -1
  103. package/dist/types/boundary/TernSecureCtx.d.ts +3 -1
  104. package/dist/types/boundary/TernSecureCtx.d.ts.map +1 -1
  105. package/dist/types/boundary/hooks/useAuth.d.ts +4 -1
  106. package/dist/types/boundary/hooks/useAuth.d.ts.map +1 -1
  107. package/dist/types/components/sign-in.d.ts +1 -2
  108. package/dist/types/components/sign-in.d.ts.map +1 -1
  109. package/dist/types/components/sign-out-button.d.ts +2 -1
  110. package/dist/types/components/sign-out-button.d.ts.map +1 -1
  111. package/dist/types/components/sign-out.d.ts +2 -1
  112. package/dist/types/components/sign-out.d.ts.map +1 -1
  113. package/dist/types/components/sign-up.d.ts.map +1 -1
  114. package/dist/types/components/ui/alert.d.ts +1 -1
  115. package/dist/types/components/ui/button.d.ts +1 -1
  116. package/dist/types/errors.d.ts +36 -2
  117. package/dist/types/errors.d.ts.map +1 -1
  118. package/dist/types/index.d.ts +0 -1
  119. package/dist/types/index.d.ts.map +1 -1
  120. package/dist/types/types.d.ts +35 -0
  121. package/dist/types/types.d.ts.map +1 -1
  122. package/dist/types/utils/construct.d.ts +20 -4
  123. package/dist/types/utils/construct.d.ts.map +1 -1
  124. package/dist/types/utils/redirect.d.ts +9 -0
  125. package/dist/types/utils/redirect.d.ts.map +1 -0
  126. package/package.json +7 -6
  127. package/dist/cjs/boundary/hooks/useUser.js +0 -44
  128. package/dist/cjs/boundary/hooks/useUser.js.map +0 -1
  129. package/dist/esm/boundary/hooks/useUser.js +0 -20
  130. package/dist/esm/boundary/hooks/useUser.js.map +0 -1
  131. package/dist/types/boundary/hooks/useUser.d.ts +0 -7
  132. package/dist/types/boundary/hooks/useUser.d.ts.map +0 -1
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var jwt_exports = {};
20
+ __export(jwt_exports, {
21
+ verifyFirebaseToken: () => verifyFirebaseToken
22
+ });
23
+ module.exports = __toCommonJS(jwt_exports);
24
+ var import_jose = require("jose");
25
+ var import_react = require("react");
26
+ const FIREBASE_ID_TOKEN_URL = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
27
+ const FIREBASE_SESSION_CERT_URL = "https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys";
28
+ const getIdTokenJWKS = (0, import_react.cache)(() => {
29
+ return (0, import_jose.createRemoteJWKSet)(new URL(FIREBASE_ID_TOKEN_URL), {
30
+ cacheMaxAge: 36e5,
31
+ // 1 hour
32
+ timeoutDuration: 5e3,
33
+ // 5 seconds
34
+ cooldownDuration: 3e4
35
+ // 30 seconds between retries
36
+ });
37
+ });
38
+ const getSessionJWKS = (0, import_react.cache)(() => {
39
+ return (0, import_jose.createRemoteJWKSet)(new URL(FIREBASE_SESSION_CERT_URL), {
40
+ cacheMaxAge: 36e5,
41
+ // 1 hour
42
+ timeoutDuration: 5e3,
43
+ // 5 seconds
44
+ cooldownDuration: 3e4
45
+ // 30 seconds between retries
46
+ });
47
+ });
48
+ function decodeJwt(token) {
49
+ try {
50
+ const [headerB64, payloadB64] = token.split(".");
51
+ const header = JSON.parse(Buffer.from(headerB64, "base64").toString());
52
+ const payload = JSON.parse(Buffer.from(payloadB64, "base64").toString());
53
+ return { header, payload };
54
+ } catch (error) {
55
+ console.error("Error decoding JWT:", error);
56
+ return null;
57
+ }
58
+ }
59
+ async function verifyFirebaseToken(token, isSessionCookie = false) {
60
+ try {
61
+ const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID;
62
+ if (!projectId) {
63
+ throw new Error("Firebase Project ID is not configured");
64
+ }
65
+ const decoded = decodeJwt(token);
66
+ if (!decoded) {
67
+ throw new Error("Invalid token format");
68
+ }
69
+ console.log("Token details:", {
70
+ header: decoded.header,
71
+ type: isSessionCookie ? "session_cookie" : "id_token"
72
+ });
73
+ let retries = 3;
74
+ let lastError = null;
75
+ while (retries > 0) {
76
+ try {
77
+ const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS();
78
+ const { payload } = await (0, import_jose.jwtVerify)(token, JWKS, {
79
+ issuer: isSessionCookie ? "https://session.firebase.google.com/" + projectId : "https://securetoken.google.com/" + projectId,
80
+ audience: projectId,
81
+ algorithms: ["RS256"]
82
+ });
83
+ const firebasePayload = payload;
84
+ const now = Math.floor(Date.now() / 1e3);
85
+ if (firebasePayload.exp <= now) {
86
+ throw new Error("Token has expired");
87
+ }
88
+ if (firebasePayload.iat > now) {
89
+ throw new Error("Token issued time is in the future");
90
+ }
91
+ if (!firebasePayload.sub) {
92
+ throw new Error("Token subject is empty");
93
+ }
94
+ if (firebasePayload.auth_time > now) {
95
+ throw new Error("Token auth time is in the future");
96
+ }
97
+ return {
98
+ valid: true,
99
+ uid: firebasePayload.sub,
100
+ email: firebasePayload.email,
101
+ emailVerified: firebasePayload.email_verified,
102
+ authTime: firebasePayload.auth_time,
103
+ issuedAt: firebasePayload.iat,
104
+ expiresAt: firebasePayload.exp
105
+ };
106
+ } catch (error) {
107
+ lastError = error;
108
+ if (error instanceof Error && error.name === "JWKSNoMatchingKey") {
109
+ console.warn(`JWKS retry attempt ${4 - retries}:`, error.message);
110
+ retries--;
111
+ if (retries > 0) {
112
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
113
+ continue;
114
+ }
115
+ }
116
+ throw error;
117
+ }
118
+ }
119
+ throw lastError || new Error("Failed to verify token after retries");
120
+ } catch (error) {
121
+ console.error("Token verification details:", {
122
+ error: error instanceof Error ? {
123
+ name: error.name,
124
+ message: error.message,
125
+ stack: error.stack
126
+ } : error,
127
+ decoded: decodeJwt(token),
128
+ //projectId,
129
+ isSessionCookie
130
+ });
131
+ return {
132
+ valid: false,
133
+ error: error instanceof Error ? error.message : "Invalid token"
134
+ };
135
+ }
136
+ }
137
+ // Annotate the CommonJS export names for ESM import in node:
138
+ 0 && (module.exports = {
139
+ verifyFirebaseToken
140
+ });
141
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/server/jwt.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\nimport { cache } from \"react\"\n\ninterface FirebaseIdTokenPayload {\n iss: string\n aud: string\n auth_time: number\n user_id: string\n sub: string\n iat: number\n exp: number\n email?: string\n email_verified?: boolean\n firebase: {\n identities: {\n [key: string]: any\n }\n sign_in_provider: string\n }\n}\n\n// Firebase public key endpoints\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\n\n// Cache the JWKS using React cache\nconst getIdTokenJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\nconst getSessionJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\n// Helper to decode JWT without verification\nfunction decodeJwt(token: string) {\n try {\n const [headerB64, payloadB64] = token.split(\".\")\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\n return { header, payload }\n } catch (error) {\n console.error(\"Error decoding JWT:\", error)\n return null\n }\n}\n\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\n try {\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\n if (!projectId) {\n throw new Error(\"Firebase Project ID is not configured\")\n }\n\n // Decode token for debugging and type checking\n const decoded = decodeJwt(token)\n if (!decoded) {\n throw new Error(\"Invalid token format\")\n }\n\n console.log(\"Token details:\", {\n header: decoded.header,\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\n })\n\n let retries = 3\n let lastError: Error | null = null\n\n while (retries > 0) {\n try {\n // Use different JWKS based on token type\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\n\n const { payload } = await jwtVerify(token, JWKS, {\n issuer: isSessionCookie\n ? \"https://session.firebase.google.com/\" + projectId\n : \"https://securetoken.google.com/\" + projectId,\n audience: projectId,\n algorithms: [\"RS256\"],\n })\n\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\n const now = Math.floor(Date.now() / 1000)\n\n // Verify token claims\n if (firebasePayload.exp <= now) {\n throw new Error(\"Token has expired\")\n }\n\n if (firebasePayload.iat > now) {\n throw new Error(\"Token issued time is in the future\")\n }\n\n if (!firebasePayload.sub) {\n throw new Error(\"Token subject is empty\")\n }\n\n if (firebasePayload.auth_time > now) {\n throw new Error(\"Token auth time is in the future\")\n }\n\n return {\n valid: true,\n uid: firebasePayload.sub,\n email: firebasePayload.email,\n emailVerified: firebasePayload.email_verified,\n authTime: firebasePayload.auth_time,\n issuedAt: firebasePayload.iat,\n expiresAt: firebasePayload.exp,\n }\n } catch (error) {\n lastError = error as Error\n if (error instanceof Error && error.name === \"JWKSNoMatchingKey\") {\n console.warn(`JWKS retry attempt ${4 - retries}:`, error.message)\n retries--\n if (retries > 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n continue\n }\n }\n throw error\n }\n }\n\n throw lastError || new Error(\"Failed to verify token after retries\")\n } catch (error) {\n console.error(\"Token verification details:\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n decoded: decodeJwt(token),\n //projectId,\n isSessionCookie,\n })\n\n return {\n valid: false,\n error: error instanceof Error ? error.message : \"Invalid token\",\n }\n }\n}\n\n"],"mappings":"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","names":[]}
@@ -83,15 +83,20 @@ async function getIdToken() {
83
83
  }
84
84
  }
85
85
  async function setServerSession(token) {
86
- const cookieStore = await (0, import_headers.cookies)();
87
- cookieStore.set("_session", token, {
88
- httpOnly: true,
89
- secure: process.env.NODE_ENV === "production",
90
- sameSite: "strict",
91
- maxAge: 60 * 60,
92
- // 1 hour
93
- path: "/"
94
- });
86
+ try {
87
+ const cookieStore = await (0, import_headers.cookies)();
88
+ cookieStore.set("_session_token", token, {
89
+ httpOnly: true,
90
+ secure: process.env.NODE_ENV === "production",
91
+ sameSite: "strict",
92
+ maxAge: 60 * 60,
93
+ // 1 hour
94
+ path: "/"
95
+ });
96
+ return { success: true, message: "Session created" };
97
+ } catch {
98
+ return { success: false, message: "Failed to create session" };
99
+ }
95
100
  }
96
101
  async function verifyTernIdToken(token) {
97
102
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/sessionTernSecure.ts"],"sourcesContent":["'use server'\n\nimport { cookies } from 'next/headers';\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\n\ninterface FirebaseAuthError extends Error {\n code?: string;\n}\n\nexport interface User {\n uid: string | null;\n email: string | null;\n }\n\nexport interface Session {\n user: User | null;\n token: string | null;\n error: Error | null;\n}\n\nexport async function createSessionCookie(idToken: string) {\n try {\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\n\n const cookieStore = await cookies();\n cookieStore.set('_session_cookie', sessionCookie, {\n maxAge: expiresIn,\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n path: '/',\n });\n return { success: true, message: 'Session created' };\n } catch (error) {\n return { success: false, message: 'Failed to create session' };\n }\n}\n\n\n\nexport async function getServerSessionCookie() {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\n\n if (!sessionCookie) {\n throw new Error('No session cookie found')\n }\n \n try {\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\n return {\n token: sessionCookie,\n userId: decondeClaims.uid\n }\n } catch (error) {\n console.error('Error verifying session:', error)\n throw new Error('Invalid Session')\n }\n}\n\n\nexport async function getIdToken() {\n const cookieStore = await cookies();\n const token = cookieStore.get('_session_token')?.value;\n\n if (!token) {\n throw new Error('No session cookie found')\n }\n \n try {\n const decodedClaims = await adminAuth.verifyIdToken(token)\n return {\n token: token,\n userId: decodedClaims.uid\n }\n } catch (error) {\n console.error('Error verifying session:', error)\n throw new Error('Invalid Session')\n }\n}\n\nexport async function setServerSession(token: string) {\n const cookieStore = await cookies();\n cookieStore.set('_session', token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 60 * 60, // 1 hour\n path: '/',\n });\n }\n\n export async function verifyTernIdToken(token: string): Promise<{ valid: boolean; uid?: string; error?: string }> {\n try {\n const decodedToken = await adminAuth.verifyIdToken(token, true);\n return { valid: true, uid: decodedToken.uid };\n } catch (error) {\n if (error instanceof Error) {\n const firebaseError = error as FirebaseAuthError;\n if (error.name === 'FirebaseAuthError') {\n // Handle specific Firebase Auth errors\n switch (firebaseError.code) {\n case 'auth/id-token-expired':\n return { valid: false, error: 'Token has expired' };\n case 'auth/id-token-revoked':\n return { valid: false, error: 'Token has been revoked' };\n case 'auth/user-disabled':\n return { valid: false, error: 'User account has been disabled' };\n default:\n return { valid: false, error: 'Invalid token' };\n }\n }\n }\n return { valid: false, error: 'Error verifying token' };\n }\n }\n \n\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\n try {\n const res = await adminAuth.verifySessionCookie(session, true);\n if (res) {\n return { valid: true, uid: res.uid };\n } else {\n return { valid: false, error: 'Invalid session'};\n }\n } catch (error) {\n return {error: error, valid: false}\n }\n }\n\n\n export async function clearSessionCookie() {\n const cookieStore = await cookies()\n \n cookieStore.delete('_session_cookie')\n cookieStore.delete('_session_token')\n cookieStore.delete('_session')\n \n try {\n // Verify if there's an active session before revoking\n const sessionCookie = cookieStore.get('_session_cookie')?.value\n if (sessionCookie) {\n // Get the decoded claims to get the user's ID\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie)\n \n // Revoke all sessions for the user\n await adminAuth.revokeRefreshTokens(decodedClaims.uid)\n }\n \n return { success: true, message: 'Session cleared successfully' }\n } catch (error) {\n console.error('Error clearing session:', error)\n // Still return success even if revoking fails, as cookies are cleared\n return { success: true, message: 'Session cookies cleared' }\n }\n }\n\n\n\n/*\n export async function GET(request: NextRequest) {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('session')?.value\n \n if (!sessionCookie) {\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\n }\n \n try {\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\n } catch (error) {\n console.error('Error verifying session cookie:', error)\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\n }\n }\n\n*/"],"mappings":"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","names":["adminAuth"]}
1
+ {"version":3,"sources":["../../../../src/app-router/server/sessionTernSecure.ts"],"sourcesContent":["'use server'\n\nimport { cookies } from 'next/headers';\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\n\ninterface FirebaseAuthError extends Error {\n code?: string;\n}\n\nexport interface User {\n uid: string | null;\n email: string | null;\n }\n\nexport interface Session {\n user: User | null;\n token: string | null;\n error: Error | null;\n}\n\nexport async function createSessionCookie(idToken: string) {\n try {\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\n\n const cookieStore = await cookies();\n cookieStore.set('_session_cookie', sessionCookie, {\n maxAge: expiresIn,\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n path: '/',\n });\n return { success: true, message: 'Session created' };\n } catch (error) {\n return { success: false, message: 'Failed to create session' };\n }\n}\n\n\n\nexport async function getServerSessionCookie() {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\n\n if (!sessionCookie) {\n throw new Error('No session cookie found')\n }\n \n try {\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\n return {\n token: sessionCookie,\n userId: decondeClaims.uid\n }\n } catch (error) {\n console.error('Error verifying session:', error)\n throw new Error('Invalid Session')\n }\n}\n\n\nexport async function getIdToken() {\n const cookieStore = await cookies();\n const token = cookieStore.get('_session_token')?.value;\n\n if (!token) {\n throw new Error('No session cookie found')\n }\n \n try {\n const decodedClaims = await adminAuth.verifyIdToken(token)\n return {\n token: token,\n userId: decodedClaims.uid\n }\n } catch (error) {\n console.error('Error verifying session:', error)\n throw new Error('Invalid Session')\n }\n}\n\nexport async function setServerSession(token: string) {\n try {\n const cookieStore = await cookies();\n cookieStore.set('_session_token', token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 60 * 60, // 1 hour\n path: '/',\n });\n return { success: true, message: 'Session created' };\n } catch {\n return { success: false, message: 'Failed to create session' };\n }\n}\n\n export async function verifyTernIdToken(token: string): Promise<{ valid: boolean; uid?: string; error?: string }> {\n try {\n const decodedToken = await adminAuth.verifyIdToken(token, true);\n return { valid: true, uid: decodedToken.uid };\n } catch (error) {\n if (error instanceof Error) {\n const firebaseError = error as FirebaseAuthError;\n if (error.name === 'FirebaseAuthError') {\n // Handle specific Firebase Auth errors\n switch (firebaseError.code) {\n case 'auth/id-token-expired':\n return { valid: false, error: 'Token has expired' };\n case 'auth/id-token-revoked':\n return { valid: false, error: 'Token has been revoked' };\n case 'auth/user-disabled':\n return { valid: false, error: 'User account has been disabled' };\n default:\n return { valid: false, error: 'Invalid token' };\n }\n }\n }\n return { valid: false, error: 'Error verifying token' };\n }\n }\n \n\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\n try {\n const res = await adminAuth.verifySessionCookie(session, true);\n if (res) {\n return { valid: true, uid: res.uid };\n } else {\n return { valid: false, error: 'Invalid session'};\n }\n } catch (error) {\n return {error: error, valid: false}\n }\n }\n\n\n export async function clearSessionCookie() {\n const cookieStore = await cookies()\n \n cookieStore.delete('_session_cookie')\n cookieStore.delete('_session_token')\n cookieStore.delete('_session')\n \n try {\n // Verify if there's an active session before revoking\n const sessionCookie = cookieStore.get('_session_cookie')?.value\n if (sessionCookie) {\n // Get the decoded claims to get the user's ID\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie)\n \n // Revoke all sessions for the user\n await adminAuth.revokeRefreshTokens(decodedClaims.uid)\n }\n \n return { success: true, message: 'Session cleared successfully' }\n } catch (error) {\n console.error('Error clearing session:', error)\n // Still return success even if revoking fails, as cookies are cleared\n return { success: true, message: 'Session cookies cleared' }\n }\n }\n\n\n\n/*\n export async function GET(request: NextRequest) {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('session')?.value\n \n if (!sessionCookie) {\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\n }\n \n try {\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\n } catch (error) {\n console.error('Error verifying session cookie:', error)\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\n }\n }\n\n*/"],"mappings":"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","names":["adminAuth"]}
@@ -18,33 +18,154 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var ternSecureMiddleware_exports = {};
20
20
  __export(ternSecureMiddleware_exports, {
21
+ createRouteMatcher: () => createRouteMatcher,
22
+ runtime: () => runtime,
21
23
  ternSecureMiddleware: () => ternSecureMiddleware
22
24
  });
23
25
  module.exports = __toCommonJS(ternSecureMiddleware_exports);
24
26
  var import_server = require("next/server");
25
- var import_auth = require("./auth");
26
- function ternSecureMiddleware(options = {}) {
27
- const { publicPaths = [], redirectTo = "/login" } = options;
28
- return async function middleware(request) {
27
+ var import_headers = require("next/headers");
28
+ var import_edge_session = require("./edge-session");
29
+ var import_jwt = require("./jwt");
30
+ const runtime = "edge";
31
+ function createRouteMatcher(patterns) {
32
+ return (request) => {
33
+ const { pathname } = request.nextUrl;
34
+ return patterns.some((pattern) => {
35
+ const regexPattern = new RegExp(
36
+ `^${pattern.replace(/\*/g, ".*").replace(/\((.*)\)/, "(?:$1)?")}$`
37
+ );
38
+ return regexPattern.test(pathname);
39
+ });
40
+ };
41
+ }
42
+ async function edgeAuth(request) {
43
+ var _a, _b, _c, _d, _e, _f;
44
+ const cookieStore = await (0, import_headers.cookies)();
45
+ async function protect() {
29
46
  const { pathname } = request.nextUrl;
30
- if (publicPaths.includes(pathname)) {
31
- return import_server.NextResponse.next();
47
+ throw new Error("Unauthorized access");
48
+ }
49
+ try {
50
+ const sessionCookie = (_a = cookieStore.get("_session_cookie")) == null ? void 0 : _a.value;
51
+ if (sessionCookie) {
52
+ const userInfo = await (0, import_jwt.verifyFirebaseToken)(sessionCookie, true);
53
+ console.log("userInfo", userInfo);
54
+ if (userInfo.valid) {
55
+ return {
56
+ user: {
57
+ uid: (_b = userInfo.uid) != null ? _b : "",
58
+ email: (_c = userInfo.email) != null ? _c : null
59
+ },
60
+ token: sessionCookie,
61
+ protect: async () => {
62
+ }
63
+ };
64
+ }
65
+ }
66
+ const idToken = (_d = cookieStore.get("_session_token")) == null ? void 0 : _d.value;
67
+ if (idToken) {
68
+ const userInfo = await (0, import_jwt.verifyFirebaseToken)(idToken, false);
69
+ if (userInfo.valid) {
70
+ return {
71
+ user: {
72
+ uid: (_e = userInfo.uid) != null ? _e : "",
73
+ email: (_f = userInfo.email) != null ? _f : null
74
+ },
75
+ token: idToken,
76
+ protect: async () => {
77
+ }
78
+ };
79
+ }
32
80
  }
81
+ return {
82
+ user: null,
83
+ token: null,
84
+ protect
85
+ };
86
+ } catch (error) {
87
+ return {
88
+ user: null,
89
+ token: null,
90
+ protect
91
+ };
92
+ }
93
+ }
94
+ async function edgeAuthSecond(request) {
95
+ var _a, _b;
96
+ async function protect() {
97
+ throw new Error("Unauthorized access");
98
+ }
99
+ try {
100
+ const sessionResult = await (0, import_edge_session.verifySession)(request);
101
+ if (sessionResult.isAuthenticated && sessionResult.user) {
102
+ return {
103
+ user: sessionResult.user,
104
+ token: ((_a = request.cookies.get("_session_cookie")) == null ? void 0 : _a.value) || ((_b = request.cookies.get("_session_token")) == null ? void 0 : _b.value) || null,
105
+ protect: async () => {
106
+ }
107
+ };
108
+ }
109
+ return {
110
+ user: null,
111
+ token: null,
112
+ protect
113
+ };
114
+ } catch (error) {
115
+ console.error("Auth check error:", error);
116
+ return {
117
+ user: null,
118
+ token: null,
119
+ protect
120
+ };
121
+ }
122
+ }
123
+ function ternSecureMiddleware(callback) {
124
+ return async function middleware(request) {
33
125
  try {
34
- const { userId, token, error } = await (0, import_auth.auth)();
35
- if (error || !userId || !token) {
36
- return import_server.NextResponse.redirect(new URL(redirectTo, request.url));
126
+ const auth = await edgeAuthSecond(request);
127
+ try {
128
+ await callback(auth, request);
129
+ const response = import_server.NextResponse.next();
130
+ if (auth.user) {
131
+ response.headers.set("x-user-id", auth.user.uid);
132
+ if (auth.user.email) {
133
+ response.headers.set("x-user-email", auth.user.email);
134
+ }
135
+ if (auth.user.emailVerified !== void 0) {
136
+ response.headers.set("x-email-verified", auth.user.emailVerified.toString());
137
+ }
138
+ if (auth.user.authTime) {
139
+ response.headers.set("x-auth-time", auth.user.authTime.toString());
140
+ }
141
+ }
142
+ return response;
143
+ } catch (error) {
144
+ if (error instanceof Error && error.message === "Unauthorized access") {
145
+ const redirectUrl = new URL("/sign-in", request.url);
146
+ redirectUrl.searchParams.set("redirect", request.nextUrl.pathname);
147
+ return import_server.NextResponse.redirect(redirectUrl);
148
+ }
149
+ throw error;
37
150
  }
38
- const response = import_server.NextResponse.next();
39
- return response;
40
151
  } catch (error) {
41
- console.error("Error in ternSecureMiddleware:", error);
42
- return import_server.NextResponse.redirect(new URL(redirectTo, request.url));
152
+ console.error("Middleware error:", {
153
+ error: error instanceof Error ? {
154
+ name: error.name,
155
+ message: error.message,
156
+ stack: error.stack
157
+ } : error,
158
+ path: request.nextUrl.pathname
159
+ });
160
+ const redirectUrl = new URL("/sign-in", request.url);
161
+ return import_server.NextResponse.redirect(redirectUrl);
43
162
  }
44
163
  };
45
164
  }
46
165
  // Annotate the CommonJS export names for ESM import in node:
47
166
  0 && (module.exports = {
167
+ createRouteMatcher,
168
+ runtime,
48
169
  ternSecureMiddleware
49
170
  });
50
171
  //# sourceMappingURL=ternSecureMiddleware.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/ternSecureMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { auth } from './auth';\n\nexport interface TernSecureMiddlewareOptions {\n publicPaths?: string[];\n redirectTo?: string;\n}\n\nexport function ternSecureMiddleware(options: TernSecureMiddlewareOptions = {}) {\n const { publicPaths = [], redirectTo = '/login' } = options;\n\n return async function middleware(request: NextRequest) {\n const { pathname } = request.nextUrl;\n\n // Check if the path is public\n if (publicPaths.includes(pathname)) {\n return NextResponse.next();\n }\n\n try {\n const { userId, token, error } = await auth();\n\n if (error || !userId || !token) {\n // If there's no valid session, redirect to login\n return NextResponse.redirect(new URL(redirectTo, request.url));\n }\n\n // If there's a valid session, allow the request to proceed\n const response = NextResponse.next();\n \n // Optionally, you can set headers here if needed\n // response.headers.set('X-User-ID', userId);\n\n return response;\n } catch (error) {\n console.error('Error in ternSecureMiddleware:', error);\n return NextResponse.redirect(new URL(redirectTo, request.url));\n }\n };\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA0C;AAC1C,kBAAqB;AAOd,SAAS,qBAAqB,UAAuC,CAAC,GAAG;AAC9E,QAAM,EAAE,cAAc,CAAC,GAAG,aAAa,SAAS,IAAI;AAEpD,SAAO,eAAe,WAAW,SAAsB;AACrD,UAAM,EAAE,SAAS,IAAI,QAAQ;AAG7B,QAAI,YAAY,SAAS,QAAQ,GAAG;AAClC,aAAO,2BAAa,KAAK;AAAA,IAC3B;AAEA,QAAI;AACF,YAAM,EAAE,QAAQ,OAAO,MAAM,IAAI,UAAM,kBAAK;AAE5C,UAAI,SAAS,CAAC,UAAU,CAAC,OAAO;AAE9B,eAAO,2BAAa,SAAS,IAAI,IAAI,YAAY,QAAQ,GAAG,CAAC;AAAA,MAC/D;AAGA,YAAM,WAAW,2BAAa,KAAK;AAKnC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,kCAAkC,KAAK;AACrD,aAAO,2BAAa,SAAS,IAAI,IAAI,YAAY,QAAQ,GAAG,CAAC;AAAA,IAC/D;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/server/ternSecureMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { cookies } from 'next/headers'\nimport { verifySession, type UserInfo } from './edge-session'\nimport { verifyFirebaseToken } from './jwt';\n\nexport const runtime = \"edge\"\n\n\ninterface Auth {\n user: UserInfo | null\n token: string | null\n protect: () => Promise<void>\n}\n\ntype MiddlewareCallback = (\n auth: Auth,\n request: NextRequest\n) => Promise<void>\n\n\n/**\n * Create a route matcher function for public paths\n */\nexport function createRouteMatcher(patterns: string[]) {\n return (request: NextRequest): boolean => {\n const { pathname } = request.nextUrl\n return patterns.some(pattern => {\n // Convert route pattern to regex\n const regexPattern = new RegExp(\n `^${pattern.replace(/\\*/g, '.*').replace(/\\((.*)\\)/, '(?:$1)?')}$`\n )\n return regexPattern.test(pathname)\n })\n }\n}\n\n\n/**\n * Edge-compatible auth check\n */\nasync function edgeAuth(request: NextRequest): Promise<Auth>{\n const cookieStore = await cookies()\n\n async function protect() {\n const { pathname } = request.nextUrl\n throw new Error('Unauthorized access')\n }\n\n try {\n // First try session cookie\n const sessionCookie = cookieStore.get(\"_session_cookie\")?.value\n if (sessionCookie) {\n const userInfo = await verifyFirebaseToken(sessionCookie, true)\n console.log('userInfo', userInfo)\n if (userInfo.valid) {\n return { \n user: {\n uid: userInfo.uid ?? '',\n email: userInfo.email ?? null,\n },\n token: sessionCookie,\n protect: async () => {}\n }\n }\n }\n\n // Then try ID token\n const idToken = cookieStore.get(\"_session_token\")?.value\n if (idToken) {\n const userInfo = await verifyFirebaseToken(idToken, false)\n if (userInfo.valid) {\n return { \n user: {\n uid: userInfo.uid ?? '',\n email: userInfo.email ?? null,\n },\n token: idToken,\n protect: async () => {}\n }\n }\n }\n\n return {\n user: null,\n token: null,\n protect\n }\n } catch (error) {\n return {\n user: null,\n token: null,\n protect\n }\n }\n}\n\n/**\n * Edge-compatible auth check\n */\nasync function edgeAuthSecond(request: NextRequest): Promise<Auth> {\n async function protect() {\n throw new Error(\"Unauthorized access\")\n }\n\n try {\n const sessionResult = await verifySession(request)\n\n if (sessionResult.isAuthenticated && sessionResult.user) {\n return {\n user: sessionResult.user,\n token: request.cookies.get(\"_session_cookie\")?.value || request.cookies.get(\"_session_token\")?.value || null,\n protect: async () => {},\n }\n }\n\n return {\n user: null,\n token: null,\n protect,\n }\n } catch (error) {\n console.error(\"Auth check error:\", error)\n return {\n user: null,\n token: null,\n protect,\n }\n }\n}\n\n\n\n/**\n * Middleware factory that handles authentication and custom logic\n * @param customHandler Optional function for additional custom logic\n */\n\nexport function ternSecureMiddleware(callback: MiddlewareCallback) {\n return async function middleware(request: NextRequest) {\n try {\n const auth = await edgeAuthSecond(request)\n\n try {\n \n await callback(auth, request)\n\n const response = NextResponse.next()\n\n if (auth.user) {\n // Set auth headers\n response.headers.set(\"x-user-id\", auth.user.uid)\n if (auth.user.email) {\n response.headers.set(\"x-user-email\", auth.user.email)\n }\n if (auth.user.emailVerified !== undefined) {\n response.headers.set(\"x-email-verified\", auth.user.emailVerified.toString())\n }\n if (auth.user.authTime) {\n response.headers.set(\"x-auth-time\", auth.user.authTime.toString())\n }\n }\n\n return response\n } catch (error) {\n // Handle unauthorized access\n if (error instanceof Error && error.message === 'Unauthorized access') {\n const redirectUrl = new URL('/sign-in', request.url)\n redirectUrl.searchParams.set('redirect', request.nextUrl.pathname)\n return NextResponse.redirect(redirectUrl)\n }\n throw error\n }\n\n } catch (error) {\n console.error(\"Middleware error:\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n path: request.nextUrl.pathname,\n })\n\n const redirectUrl = new URL(\"/sign-in\", request.url)\n return NextResponse.redirect(redirectUrl)\n }\n }\n}\n"],"mappings":"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","names":[]}