@tern-secure/nextjs 4.1.0 → 4.2.1

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 (79) hide show
  1. package/dist/cjs/app-router/{server → admin}/index.js +4 -10
  2. package/dist/cjs/app-router/admin/index.js.map +1 -0
  3. package/dist/cjs/app-router/{server → admin}/sessionTernSecure.js +14 -9
  4. package/dist/cjs/app-router/admin/sessionTernSecure.js.map +1 -0
  5. package/dist/cjs/components/sign-in.js +1 -1
  6. package/dist/cjs/components/sign-in.js.map +1 -1
  7. package/dist/cjs/components/sign-out-button.js +1 -1
  8. package/dist/cjs/components/sign-out-button.js.map +1 -1
  9. package/dist/cjs/components/sign-out.js +1 -1
  10. package/dist/cjs/components/sign-out.js.map +1 -1
  11. package/dist/cjs/{app-router/server → server}/auth.js +42 -28
  12. package/dist/cjs/server/auth.js.map +1 -0
  13. package/dist/cjs/server/edge-session.js +78 -0
  14. package/dist/cjs/server/edge-session.js.map +1 -0
  15. package/dist/cjs/server/index.js +36 -0
  16. package/dist/cjs/server/index.js.map +1 -0
  17. package/dist/cjs/server/jwt-edge.js +88 -0
  18. package/dist/cjs/server/jwt-edge.js.map +1 -0
  19. package/dist/cjs/server/jwt.js +141 -0
  20. package/dist/cjs/server/jwt.js.map +1 -0
  21. package/dist/cjs/server/ternSecureMiddleware.js +117 -0
  22. package/dist/cjs/server/ternSecureMiddleware.js.map +1 -0
  23. package/dist/esm/app-router/{server → admin}/index.js +1 -5
  24. package/dist/esm/app-router/admin/index.js.map +1 -0
  25. package/dist/esm/app-router/{server → admin}/sessionTernSecure.js +14 -9
  26. package/dist/esm/app-router/admin/sessionTernSecure.js.map +1 -0
  27. package/dist/esm/components/sign-in.js +1 -1
  28. package/dist/esm/components/sign-in.js.map +1 -1
  29. package/dist/esm/components/sign-out-button.js +1 -1
  30. package/dist/esm/components/sign-out-button.js.map +1 -1
  31. package/dist/esm/components/sign-out.js +1 -1
  32. package/dist/esm/components/sign-out.js.map +1 -1
  33. package/dist/esm/server/auth.js +59 -0
  34. package/dist/esm/server/auth.js.map +1 -0
  35. package/dist/esm/server/edge-session.js +54 -0
  36. package/dist/esm/server/edge-session.js.map +1 -0
  37. package/dist/esm/server/index.js +9 -0
  38. package/dist/esm/server/index.js.map +1 -0
  39. package/dist/esm/server/jwt-edge.js +64 -0
  40. package/dist/esm/server/jwt-edge.js.map +1 -0
  41. package/dist/esm/server/jwt.js +117 -0
  42. package/dist/esm/server/jwt.js.map +1 -0
  43. package/dist/esm/server/ternSecureMiddleware.js +91 -0
  44. package/dist/esm/server/ternSecureMiddleware.js.map +1 -0
  45. package/dist/types/app-router/{server → admin}/index.d.ts +1 -3
  46. package/dist/types/app-router/admin/index.d.ts.map +1 -0
  47. package/dist/types/app-router/{server → admin}/sessionTernSecure.d.ts +4 -1
  48. package/dist/types/app-router/admin/sessionTernSecure.d.ts.map +1 -0
  49. package/dist/types/server/auth.d.ts +19 -0
  50. package/dist/types/server/auth.d.ts.map +1 -0
  51. package/dist/types/server/edge-session.d.ts +15 -0
  52. package/dist/types/server/edge-session.d.ts.map +1 -0
  53. package/dist/types/server/index.d.ts +4 -0
  54. package/dist/types/server/index.d.ts.map +1 -0
  55. package/dist/types/server/jwt-edge.d.ts +16 -0
  56. package/dist/types/server/jwt-edge.d.ts.map +1 -0
  57. package/dist/types/server/jwt.d.ts +20 -0
  58. package/dist/types/server/jwt.d.ts.map +1 -0
  59. package/dist/types/server/ternSecureMiddleware.d.ts +20 -0
  60. package/dist/types/server/ternSecureMiddleware.d.ts.map +1 -0
  61. package/package.json +13 -5
  62. package/server/package.json +5 -0
  63. package/dist/cjs/app-router/server/auth.js.map +0 -1
  64. package/dist/cjs/app-router/server/index.js.map +0 -1
  65. package/dist/cjs/app-router/server/sessionTernSecure.js.map +0 -1
  66. package/dist/cjs/app-router/server/ternSecureMiddleware.js +0 -50
  67. package/dist/cjs/app-router/server/ternSecureMiddleware.js.map +0 -1
  68. package/dist/esm/app-router/server/auth.js +0 -47
  69. package/dist/esm/app-router/server/auth.js.map +0 -1
  70. package/dist/esm/app-router/server/index.js.map +0 -1
  71. package/dist/esm/app-router/server/sessionTernSecure.js.map +0 -1
  72. package/dist/esm/app-router/server/ternSecureMiddleware.js +0 -26
  73. package/dist/esm/app-router/server/ternSecureMiddleware.js.map +0 -1
  74. package/dist/types/app-router/server/auth.d.ts +0 -7
  75. package/dist/types/app-router/server/auth.d.ts.map +0 -1
  76. package/dist/types/app-router/server/index.d.ts.map +0 -1
  77. package/dist/types/app-router/server/sessionTernSecure.d.ts.map +0 -1
  78. package/dist/types/app-router/server/ternSecureMiddleware.d.ts +0 -7
  79. package/dist/types/app-router/server/ternSecureMiddleware.d.ts.map +0 -1
@@ -0,0 +1,54 @@
1
+ import { verifyFirebaseToken } from "./jwt-edge";
2
+ async function verifySession(request) {
3
+ var _a, _b, _c, _d, _e, _f;
4
+ try {
5
+ const sessionCookie = (_a = request.cookies.get("_session_cookie")) == null ? void 0 : _a.value;
6
+ if (sessionCookie) {
7
+ const result = await verifyFirebaseToken(sessionCookie, true);
8
+ if (result.valid) {
9
+ return {
10
+ isAuthenticated: true,
11
+ user: {
12
+ uid: (_b = result.uid) != null ? _b : "",
13
+ email: result.email || null,
14
+ emailVerified: (_c = result.emailVerified) != null ? _c : false,
15
+ disabled: false
16
+ }
17
+ };
18
+ }
19
+ console.log("Session cookie verification failed:", result.error);
20
+ }
21
+ const idToken = (_d = request.cookies.get("_session_token")) == null ? void 0 : _d.value;
22
+ if (idToken) {
23
+ const result = await verifyFirebaseToken(idToken, false);
24
+ if (result.valid) {
25
+ return {
26
+ isAuthenticated: true,
27
+ user: {
28
+ uid: (_e = result.uid) != null ? _e : "",
29
+ email: result.email || null,
30
+ emailVerified: (_f = result.emailVerified) != null ? _f : false,
31
+ disabled: false
32
+ }
33
+ };
34
+ }
35
+ console.log("ID token verification failed:", result.error);
36
+ }
37
+ return {
38
+ isAuthenticated: false,
39
+ user: null,
40
+ error: "No valid session found"
41
+ };
42
+ } catch (error) {
43
+ console.error("Session verification error:", error);
44
+ return {
45
+ isAuthenticated: false,
46
+ user: null,
47
+ error: error instanceof Error ? error.message : "Session verification failed"
48
+ };
49
+ }
50
+ }
51
+ export {
52
+ verifySession
53
+ };
54
+ //# sourceMappingURL=edge-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/edge-session.ts"],"sourcesContent":["import { verifyFirebaseToken } from \"./jwt-edge\"\nimport type { NextRequest } from \"next/server\"\n\nexport interface UserInfo {\n uid: string\n email: string | null\n emailVerified?: boolean\n authTime?: number\n disabled?: boolean\n}\n\n\nexport interface SessionResult {\n isAuthenticated: boolean\n user: UserInfo | null\n error?: string\n}\n\n\nexport async function verifySession(request: NextRequest): Promise<SessionResult> {\n try {\n //const cookieStore = await cookies()\n\n // First try session cookie\n const sessionCookie = request.cookies.get(\"_session_cookie\")?.value\n if (sessionCookie) {\n const result = await verifyFirebaseToken(sessionCookie, true)\n if (result.valid) {\n return {\n isAuthenticated: true,\n user: {\n uid: result.uid ?? '',\n email: result.email || null,\n emailVerified: result.emailVerified ?? false,\n disabled: false,\n },\n }\n }\n console.log(\"Session cookie verification failed:\", result.error)\n }\n\n // Then try ID token\n const idToken = request.cookies.get(\"_session_token\")?.value\n if (idToken) {\n const result = await verifyFirebaseToken(idToken, false)\n if (result.valid) {\n return {\n isAuthenticated: true,\n user: {\n uid: result.uid ?? '',\n email: result.email || null,\n emailVerified: result.emailVerified ?? false,\n disabled: false,\n },\n }\n }\n console.log(\"ID token verification failed:\", result.error)\n }\n\n return {\n isAuthenticated: false,\n user: null,\n error: \"No valid session found\",\n }\n } catch (error) {\n console.error(\"Session verification error:\", error)\n return {\n isAuthenticated: false,\n user: null,\n error: error instanceof Error ? error.message : \"Session verification failed\",\n }\n }\n}"],"mappings":"AAAA,SAAS,2BAA2B;AAmBpC,eAAsB,cAAc,SAA8C;AAnBlF;AAoBE,MAAI;AAIF,UAAM,iBAAgB,aAAQ,QAAQ,IAAI,iBAAiB,MAArC,mBAAwC;AAC9D,QAAI,eAAe;AACjB,YAAM,SAAS,MAAM,oBAAoB,eAAe,IAAI;AAC5D,UAAI,OAAO,OAAO;AAChB,eAAO;AAAA,UACL,iBAAiB;AAAA,UACjB,MAAM;AAAA,YACJ,MAAK,YAAO,QAAP,YAAc;AAAA,YACnB,OAAO,OAAO,SAAS;AAAA,YACvB,gBAAe,YAAO,kBAAP,YAAwB;AAAA,YACvC,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AACA,cAAQ,IAAI,uCAAuC,OAAO,KAAK;AAAA,IACjE;AAGA,UAAM,WAAU,aAAQ,QAAQ,IAAI,gBAAgB,MAApC,mBAAuC;AACvD,QAAI,SAAS;AACX,YAAM,SAAS,MAAM,oBAAoB,SAAS,KAAK;AACvD,UAAI,OAAO,OAAO;AAChB,eAAO;AAAA,UACL,iBAAiB;AAAA,UACjB,MAAM;AAAA,YACJ,MAAK,YAAO,QAAP,YAAc;AAAA,YACnB,OAAO,OAAO,SAAS;AAAA,YACvB,gBAAe,YAAO,kBAAP,YAAwB;AAAA,YACvC,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AACA,cAAQ,IAAI,iCAAiC,OAAO,KAAK;AAAA,IAC3D;AAEA,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,+BAA+B,KAAK;AAClD,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,9 @@
1
+ import { ternSecureMiddleware, createRouteMatcher } from "./ternSecureMiddleware";
2
+ import { auth, getUserInfo } from "./auth";
3
+ export {
4
+ auth,
5
+ createRouteMatcher,
6
+ getUserInfo,
7
+ ternSecureMiddleware
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["\n\nexport { ternSecureMiddleware, createRouteMatcher } from './ternSecureMiddleware'\nexport { auth, getUserInfo } from './auth'\nexport type { AuthResult } from './auth'"],"mappings":"AAEA,SAAS,sBAAsB,0BAA0B;AACzD,SAAS,MAAM,mBAAmB;","names":[]}
@@ -0,0 +1,64 @@
1
+ import { jwtVerify, createRemoteJWKSet } from "jose";
2
+ const JWKS_URLS = {
3
+ session: new URL("https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com"),
4
+ token: new URL("https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys")
5
+ };
6
+ const JWKS = {
7
+ session: createRemoteJWKSet(new URL(JWKS_URLS.session), {
8
+ cacheMaxAge: 36e5,
9
+ // 1 hour
10
+ timeoutDuration: 5e3,
11
+ // 5 seconds
12
+ cooldownDuration: 3e4
13
+ // 30 seconds between retries
14
+ }),
15
+ token: createRemoteJWKSet(new URL(JWKS_URLS.token), {
16
+ cacheMaxAge: 36e5,
17
+ // 1 hour
18
+ timeoutDuration: 5e3,
19
+ // 5 seconds
20
+ cooldownDuration: 3e4
21
+ // 30 seconds between retries
22
+ })
23
+ };
24
+ async function verifyFirebaseToken(token, isSessionCookie = false) {
25
+ try {
26
+ const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID;
27
+ if (!projectId) {
28
+ throw new Error("Firebase Project ID is not configured");
29
+ }
30
+ const keySet = isSessionCookie ? JWKS.session : JWKS.token;
31
+ const { payload } = await jwtVerify(token, keySet, {
32
+ issuer: isSessionCookie ? "https://session.firebase.google.com/" + projectId : "https://securetoken.google.com/" + projectId,
33
+ audience: projectId,
34
+ algorithms: ["RS256"]
35
+ });
36
+ const now = Math.floor(Date.now() / 1e3);
37
+ if (payload.exp && payload.exp <= now) {
38
+ throw new Error("Token has expired");
39
+ }
40
+ if (payload.iat && payload.iat > now) {
41
+ throw new Error("Token issued time is in the future");
42
+ }
43
+ if (!payload.sub) {
44
+ throw new Error("Token subject is empty");
45
+ }
46
+ return {
47
+ valid: true,
48
+ uid: payload.sub,
49
+ email: payload.email,
50
+ emailVerified: payload.email_verified,
51
+ authTime: payload.auth_time
52
+ };
53
+ } catch (error) {
54
+ console.error("Token verification error:", error);
55
+ return {
56
+ valid: false,
57
+ error: error instanceof Error ? error.message : "Invalid token"
58
+ };
59
+ }
60
+ }
61
+ export {
62
+ verifyFirebaseToken
63
+ };
64
+ //# sourceMappingURL=jwt-edge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/jwt-edge.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\n\n// Firebase public key endpoints with simplified configuration for Edge\nconst JWKS_URLS = {\n session: new URL(\"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"),\n token: new URL(\"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\")\n}\n\n// Simplified JWKS for Edge Runtime\nconst JWKS = {\n session: createRemoteJWKSet(new URL(JWKS_URLS.session), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n }),\n token: createRemoteJWKSet(new URL(JWKS_URLS.token), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\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 const keySet = isSessionCookie ? JWKS.session : JWKS.token\n\n\n const { payload } = await jwtVerify(token, keySet, {\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 now = Math.floor(Date.now() / 1000)\n if (payload.exp && payload.exp <= now) {\n throw new Error(\"Token has expired\")\n }\n\n if (payload.iat && payload.iat > now) {\n throw new Error(\"Token issued time is in the future\")\n }\n\n if (!payload.sub) {\n throw new Error(\"Token subject is empty\")\n }\n\n return {\n valid: true,\n uid: payload.sub,\n email: payload.email as string | undefined,\n emailVerified: payload.email_verified as boolean | undefined,\n authTime: payload.auth_time as number,\n }\n } catch (error) {\n console.error(\"Token verification error:\", error)\n return {\n valid: false,\n error: error instanceof Error ? error.message : \"Invalid token\",\n }\n }\n}"],"mappings":"AAAA,SAAS,WAAW,0BAA0B;AAG9C,MAAM,YAAY;AAAA,EAChB,SAAS,IAAI,IAAI,0FAA0F;AAAA,EAC3G,OAAO,IAAI,IAAI,mEAAmE;AACpF;AAGA,MAAM,OAAO;AAAA,EACT,SAAS,mBAAmB,IAAI,IAAI,UAAU,OAAO,GAAG;AAAA,IACtD,aAAa;AAAA;AAAA,IACb,iBAAiB;AAAA;AAAA,IACjB,kBAAkB;AAAA;AAAA,EACpB,CAAC;AAAA,EACD,OAAO,mBAAmB,IAAI,IAAI,UAAU,KAAK,GAAG;AAAA,IAClD,aAAa;AAAA;AAAA,IACb,iBAAiB;AAAA;AAAA,IACjB,kBAAkB;AAAA;AAAA,EACpB,CAAC;AACH;AAEF,eAAsB,oBAAoB,OAAe,kBAAkB,OAAO;AAChF,MAAI;AACF,UAAM,YAAY,QAAQ,IAAI;AAC9B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,UAAM,SAAS,kBAAkB,KAAK,UAAU,KAAK;AAGrD,UAAM,EAAE,QAAQ,IAAI,MAAM,UAAU,OAAO,QAAQ;AAAA,MACjD,QAAQ,kBACJ,yCAAyC,YACzC,oCAAoC;AAAA,MACxC,UAAU;AAAA,MACV,YAAY,CAAC,OAAO;AAAA,IACtB,CAAC;AAED,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAI,QAAQ,OAAO,QAAQ,OAAO,KAAK;AACrC,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACrC;AAEA,QAAI,QAAQ,OAAO,QAAQ,MAAM,KAAK;AACpC,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AAEA,QAAI,CAAC,QAAQ,KAAK;AAChB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,KAAK,QAAQ;AAAA,MACb,OAAO,QAAQ;AAAA,MACf,eAAe,QAAQ;AAAA,MACvB,UAAU,QAAQ;AAAA,IACpB;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,117 @@
1
+ import { jwtVerify, createRemoteJWKSet } from "jose";
2
+ import { cache } from "react";
3
+ const FIREBASE_ID_TOKEN_URL = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
4
+ const FIREBASE_SESSION_CERT_URL = "https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys";
5
+ const getIdTokenJWKS = cache(() => {
6
+ return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {
7
+ cacheMaxAge: 36e5,
8
+ // 1 hour
9
+ timeoutDuration: 5e3,
10
+ // 5 seconds
11
+ cooldownDuration: 3e4
12
+ // 30 seconds between retries
13
+ });
14
+ });
15
+ const getSessionJWKS = cache(() => {
16
+ return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {
17
+ cacheMaxAge: 36e5,
18
+ // 1 hour
19
+ timeoutDuration: 5e3,
20
+ // 5 seconds
21
+ cooldownDuration: 3e4
22
+ // 30 seconds between retries
23
+ });
24
+ });
25
+ function decodeJwt(token) {
26
+ try {
27
+ const [headerB64, payloadB64] = token.split(".");
28
+ const header = JSON.parse(Buffer.from(headerB64, "base64").toString());
29
+ const payload = JSON.parse(Buffer.from(payloadB64, "base64").toString());
30
+ return { header, payload };
31
+ } catch (error) {
32
+ console.error("Error decoding JWT:", error);
33
+ return null;
34
+ }
35
+ }
36
+ async function verifyFirebaseToken(token, isSessionCookie = false) {
37
+ try {
38
+ const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID;
39
+ if (!projectId) {
40
+ throw new Error("Firebase Project ID is not configured");
41
+ }
42
+ const decoded = decodeJwt(token);
43
+ if (!decoded) {
44
+ throw new Error("Invalid token format");
45
+ }
46
+ console.log("Token details:", {
47
+ header: decoded.header,
48
+ type: isSessionCookie ? "session_cookie" : "id_token"
49
+ });
50
+ let retries = 3;
51
+ let lastError = null;
52
+ while (retries > 0) {
53
+ try {
54
+ const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS();
55
+ const { payload } = await jwtVerify(token, JWKS, {
56
+ issuer: isSessionCookie ? "https://session.firebase.google.com/" + projectId : "https://securetoken.google.com/" + projectId,
57
+ audience: projectId,
58
+ algorithms: ["RS256"]
59
+ });
60
+ const firebasePayload = payload;
61
+ const now = Math.floor(Date.now() / 1e3);
62
+ if (firebasePayload.exp <= now) {
63
+ throw new Error("Token has expired");
64
+ }
65
+ if (firebasePayload.iat > now) {
66
+ throw new Error("Token issued time is in the future");
67
+ }
68
+ if (!firebasePayload.sub) {
69
+ throw new Error("Token subject is empty");
70
+ }
71
+ if (firebasePayload.auth_time > now) {
72
+ throw new Error("Token auth time is in the future");
73
+ }
74
+ return {
75
+ valid: true,
76
+ uid: firebasePayload.sub,
77
+ email: firebasePayload.email,
78
+ emailVerified: firebasePayload.email_verified,
79
+ authTime: firebasePayload.auth_time,
80
+ issuedAt: firebasePayload.iat,
81
+ expiresAt: firebasePayload.exp
82
+ };
83
+ } catch (error) {
84
+ lastError = error;
85
+ if (error instanceof Error && error.name === "JWKSNoMatchingKey") {
86
+ console.warn(`JWKS retry attempt ${4 - retries}:`, error.message);
87
+ retries--;
88
+ if (retries > 0) {
89
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
90
+ continue;
91
+ }
92
+ }
93
+ throw error;
94
+ }
95
+ }
96
+ throw lastError || new Error("Failed to verify token after retries");
97
+ } catch (error) {
98
+ console.error("Token verification details:", {
99
+ error: error instanceof Error ? {
100
+ name: error.name,
101
+ message: error.message,
102
+ stack: error.stack
103
+ } : error,
104
+ decoded: decodeJwt(token),
105
+ //projectId,
106
+ isSessionCookie
107
+ });
108
+ return {
109
+ valid: false,
110
+ error: error instanceof Error ? error.message : "Invalid token"
111
+ };
112
+ }
113
+ }
114
+ export {
115
+ verifyFirebaseToken
116
+ };
117
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/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}"],"mappings":"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","names":[]}
@@ -0,0 +1,91 @@
1
+ import { NextResponse } from "next/server";
2
+ import { verifySession } from "./edge-session";
3
+ const runtime = "edge";
4
+ function createRouteMatcher(patterns) {
5
+ return (request) => {
6
+ const { pathname } = request.nextUrl;
7
+ return patterns.some((pattern) => {
8
+ const regexPattern = new RegExp(
9
+ `^${pattern.replace(/\*/g, ".*").replace(/\((.*)\)/, "(?:$1)?")}$`
10
+ );
11
+ return regexPattern.test(pathname);
12
+ });
13
+ };
14
+ }
15
+ async function edgeAuth(request) {
16
+ var _a, _b;
17
+ async function protect() {
18
+ throw new Error("Unauthorized access");
19
+ }
20
+ try {
21
+ const sessionResult = await verifySession(request);
22
+ if (sessionResult.isAuthenticated && sessionResult.user) {
23
+ return {
24
+ user: sessionResult.user,
25
+ token: ((_a = request.cookies.get("_session_cookie")) == null ? void 0 : _a.value) || ((_b = request.cookies.get("_session_token")) == null ? void 0 : _b.value) || null,
26
+ protect: async () => {
27
+ }
28
+ };
29
+ }
30
+ return {
31
+ user: null,
32
+ token: null,
33
+ protect
34
+ };
35
+ } catch (error) {
36
+ console.error("Auth check error:", error);
37
+ return {
38
+ user: null,
39
+ token: null,
40
+ protect
41
+ };
42
+ }
43
+ }
44
+ function ternSecureMiddleware(callback) {
45
+ return async function middleware(request) {
46
+ try {
47
+ const auth = await edgeAuth(request);
48
+ try {
49
+ await callback(auth, request);
50
+ const response = NextResponse.next();
51
+ if (auth.user) {
52
+ response.headers.set("x-user-id", auth.user.uid);
53
+ if (auth.user.email) {
54
+ response.headers.set("x-user-email", auth.user.email);
55
+ }
56
+ if (auth.user.emailVerified !== void 0) {
57
+ response.headers.set("x-email-verified", auth.user.emailVerified.toString());
58
+ }
59
+ if (auth.user.authTime) {
60
+ response.headers.set("x-auth-time", auth.user.authTime.toString());
61
+ }
62
+ }
63
+ return response;
64
+ } catch (error) {
65
+ if (error instanceof Error && error.message === "Unauthorized access") {
66
+ const redirectUrl = new URL("/sign-in", request.url);
67
+ redirectUrl.searchParams.set("redirect", request.nextUrl.pathname);
68
+ return NextResponse.redirect(redirectUrl);
69
+ }
70
+ throw error;
71
+ }
72
+ } catch (error) {
73
+ console.error("Middleware error:", {
74
+ error: error instanceof Error ? {
75
+ name: error.name,
76
+ message: error.message,
77
+ stack: error.stack
78
+ } : error,
79
+ path: request.nextUrl.pathname
80
+ });
81
+ const redirectUrl = new URL("/sign-in", request.url);
82
+ return NextResponse.redirect(redirectUrl);
83
+ }
84
+ };
85
+ }
86
+ export {
87
+ createRouteMatcher,
88
+ runtime,
89
+ ternSecureMiddleware
90
+ };
91
+ //# sourceMappingURL=ternSecureMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/ternSecureMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { verifySession, type UserInfo } from './edge-session'\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 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 edgeAuth(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}"],"mappings":"AAAA,SAAsB,oBAAoB;AAC1C,SAAS,qBAAoC;AAEtC,MAAM,UAAU;AAkBhB,SAAS,mBAAmB,UAAoB;AACrD,SAAO,CAAC,YAAkC;AACxC,UAAM,EAAE,SAAS,IAAI,QAAQ;AAC7B,WAAO,SAAS,KAAK,aAAW;AAE9B,YAAM,eAAe,IAAI;AAAA,QACvB,IAAI,QAAQ,QAAQ,OAAO,IAAI,EAAE,QAAQ,YAAY,SAAS,CAAC;AAAA,MACjE;AACA,aAAO,aAAa,KAAK,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH;AACF;AAMA,eAAe,SAAS,SAAqC;AAtC7D;AAuCE,iBAAe,UAAU;AACvB,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACvC;AAEA,MAAI;AACF,UAAM,gBAAgB,MAAM,cAAc,OAAO;AAEjD,QAAI,cAAc,mBAAmB,cAAc,MAAM;AACvD,aAAO;AAAA,QACL,MAAM,cAAc;AAAA,QACpB,SAAO,aAAQ,QAAQ,IAAI,iBAAiB,MAArC,mBAAwC,YAAS,aAAQ,QAAQ,IAAI,gBAAgB,MAApC,mBAAuC,UAAS;AAAA,QACxG,SAAS,YAAY;AAAA,QAAC;AAAA,MACxB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,qBAAqB,KAAK;AACxC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,qBAAqB,UAA8B;AACjE,SAAO,eAAe,WAAW,SAAsB;AACrD,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,OAAO;AAEnC,UAAI;AAEF,cAAM,SAAS,MAAM,OAAO;AAE5B,cAAM,WAAW,aAAa,KAAK;AAEnC,YAAI,KAAK,MAAM;AAEb,mBAAS,QAAQ,IAAI,aAAa,KAAK,KAAK,GAAG;AAC/C,cAAI,KAAK,KAAK,OAAO;AACnB,qBAAS,QAAQ,IAAI,gBAAgB,KAAK,KAAK,KAAK;AAAA,UACtD;AACA,cAAI,KAAK,KAAK,kBAAkB,QAAW;AACzC,qBAAS,QAAQ,IAAI,oBAAoB,KAAK,KAAK,cAAc,SAAS,CAAC;AAAA,UAC7E;AACA,cAAI,KAAK,KAAK,UAAU;AACtB,qBAAS,QAAQ,IAAI,eAAe,KAAK,KAAK,SAAS,SAAS,CAAC;AAAA,UACnE;AAAA,QACF;AAEA,eAAO;AAAA,MACT,SAAS,OAAO;AAEd,YAAI,iBAAiB,SAAS,MAAM,YAAY,uBAAuB;AACrE,gBAAM,cAAc,IAAI,IAAI,YAAY,QAAQ,GAAG;AACnD,sBAAY,aAAa,IAAI,YAAY,QAAQ,QAAQ,QAAQ;AACjE,iBAAO,aAAa,SAAS,WAAW;AAAA,QAC1C;AACA,cAAM;AAAA,MACR;AAAA,IAEF,SAAS,OAAO;AACd,cAAQ,MAAM,qBAAqB;AAAA,QACjC,OACE,iBAAiB,QACb;AAAA,UACE,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,UACf,OAAO,MAAM;AAAA,QACf,IACA;AAAA,QACN,MAAM,QAAQ,QAAQ;AAAA,MACxB,CAAC;AAED,YAAM,cAAc,IAAI,IAAI,YAAY,QAAQ,GAAG;AACnD,aAAO,aAAa,SAAS,WAAW;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
@@ -1,5 +1,3 @@
1
- export { adminTernSecureAuth, adminTernSecureDb } from '../../utils/admin-init';
2
- export { ternSecureMiddleware } from './ternSecureMiddleware';
3
1
  export { verifyTernSessionCookie, createSessionCookie } from './sessionTernSecure';
4
- export { auth } from './auth';
2
+ export { adminTernSecureAuth, adminTernSecureDb } from '../../utils/admin-init';
5
3
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -19,7 +19,10 @@ export declare function getIdToken(): Promise<{
19
19
  token: string;
20
20
  userId: string;
21
21
  }>;
22
- export declare function setServerSession(token: string): Promise<void>;
22
+ export declare function setServerSession(token: string): Promise<{
23
+ success: boolean;
24
+ message: string;
25
+ }>;
23
26
  export declare function verifyTernIdToken(token: string): Promise<{
24
27
  valid: boolean;
25
28
  uid?: string;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionTernSecure.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/sessionTernSecure.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,IAAI;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAEH,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACvB;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM;;;GAgBxD;AAID,wBAAsB,sBAAsB;;;GAkB3C;AAGD,wBAAsB,UAAU;;;GAkB/B;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM;;;GAcnD;AAEC,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAuBhH;AAGD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAWlH;AAGD,wBAAsB,kBAAkB;;;GAwBvC"}
@@ -0,0 +1,19 @@
1
+ import type { UserInfo } from "./edge-session";
2
+ export interface AuthResult {
3
+ user: UserInfo | null;
4
+ token: string | null;
5
+ error: Error | null;
6
+ }
7
+ /**
8
+ * Get the current authenticated user from the session or token
9
+ */
10
+ export declare function auth(): Promise<AuthResult>;
11
+ /**
12
+ * Type guard to check if user is authenticated
13
+ */
14
+ export declare function isAuthenticated(): Promise<boolean>;
15
+ /**
16
+ * Get user info from auth result
17
+ */
18
+ export declare function getUserInfo(): Promise<UserInfo | null>;
19
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/server/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,gBAAgB,CAAA;AAG7D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAGC;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAuClD;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAGxD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAY1D"}
@@ -0,0 +1,15 @@
1
+ import type { NextRequest } from "next/server";
2
+ export interface UserInfo {
3
+ uid: string;
4
+ email: string | null;
5
+ emailVerified?: boolean;
6
+ authTime?: number;
7
+ disabled?: boolean;
8
+ }
9
+ export interface SessionResult {
10
+ isAuthenticated: boolean;
11
+ user: UserInfo | null;
12
+ error?: string;
13
+ }
14
+ export declare function verifySession(request: NextRequest): Promise<SessionResult>;
15
+ //# sourceMappingURL=edge-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-session.d.ts","sourceRoot":"","sources":["../../../src/server/edge-session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAGD,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,OAAO,CAAA;IACxB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAGD,wBAAsB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAqDhF"}
@@ -0,0 +1,4 @@
1
+ export { ternSecureMiddleware, createRouteMatcher } from './ternSecureMiddleware';
2
+ export { auth, getUserInfo } from './auth';
3
+ export type { AuthResult } from './auth';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACjF,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAC1C,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA"}
@@ -0,0 +1,16 @@
1
+ export declare function verifyFirebaseToken(token: string, isSessionCookie?: boolean): Promise<{
2
+ valid: boolean;
3
+ uid: string;
4
+ email: string | undefined;
5
+ emailVerified: boolean | undefined;
6
+ authTime: number;
7
+ error?: undefined;
8
+ } | {
9
+ valid: boolean;
10
+ error: string;
11
+ uid?: undefined;
12
+ email?: undefined;
13
+ emailVerified?: undefined;
14
+ authTime?: undefined;
15
+ }>;
16
+ //# sourceMappingURL=jwt-edge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-edge.d.ts","sourceRoot":"","sources":["../../../src/server/jwt-edge.ts"],"names":[],"mappings":"AAsBA,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,UAAQ;;;WAkClD,MAAM,GAAG,SAAS;mBACD,OAAO,GAAG,SAAS;cAC7B,MAAM;;;;;;;;;GAS1C"}
@@ -0,0 +1,20 @@
1
+ export declare function verifyFirebaseToken(token: string, isSessionCookie?: boolean): Promise<{
2
+ valid: boolean;
3
+ uid: string;
4
+ email: string | undefined;
5
+ emailVerified: boolean | undefined;
6
+ authTime: number;
7
+ issuedAt: number;
8
+ expiresAt: number;
9
+ error?: undefined;
10
+ } | {
11
+ valid: boolean;
12
+ error: string;
13
+ uid?: undefined;
14
+ email?: undefined;
15
+ emailVerified?: undefined;
16
+ authTime?: undefined;
17
+ issuedAt?: undefined;
18
+ expiresAt?: undefined;
19
+ }>;
20
+ //# sourceMappingURL=jwt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/server/jwt.ts"],"names":[],"mappings":"AAuDA,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,UAAQ;;;;;;;;;;;;;;;;;;GAkG/E"}
@@ -0,0 +1,20 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { type UserInfo } from './edge-session';
3
+ export declare const runtime = "edge";
4
+ interface Auth {
5
+ user: UserInfo | null;
6
+ token: string | null;
7
+ protect: () => Promise<void>;
8
+ }
9
+ type MiddlewareCallback = (auth: Auth, request: NextRequest) => Promise<void>;
10
+ /**
11
+ * Create a route matcher function for public paths
12
+ */
13
+ export declare function createRouteMatcher(patterns: string[]): (request: NextRequest) => boolean;
14
+ /**
15
+ * Middleware factory that handles authentication and custom logic
16
+ * @param customHandler Optional function for additional custom logic
17
+ */
18
+ export declare function ternSecureMiddleware(callback: MiddlewareCallback): (request: NextRequest) => Promise<NextResponse<unknown>>;
19
+ export {};
20
+ //# sourceMappingURL=ternSecureMiddleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ternSecureMiddleware.d.ts","sourceRoot":"","sources":["../../../src/server/ternSecureMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE7D,eAAO,MAAM,OAAO,SAAS,CAAA;AAG7B,UAAU,IAAI;IACZ,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAED,KAAK,kBAAkB,GAAG,CACxB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,IAAI,CAAC,CAAA;AAGlB;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAClC,WAAW,KAAG,OAAO,CAUvC;AAuCD;;;GAGG;AAEH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,kBAAkB,aACrB,WAAW,oCAoDtD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tern-secure/nextjs",
3
- "version": "4.1.0",
3
+ "version": "4.2.1",
4
4
  "packageManager": "npm@11.0.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -44,7 +44,9 @@
44
44
  },
45
45
  "types": "./dist/types/index.d.ts",
46
46
  "files": [
47
- "dist"
47
+ "dist",
48
+ "server",
49
+ "admin"
48
50
  ],
49
51
  "sideEffects": false,
50
52
  "peerDependencies": {
@@ -61,9 +63,14 @@
61
63
  "require": "./dist/cjs/index.js"
62
64
  },
63
65
  "./server": {
64
- "types": "./dist/types/app-router/server/index.d.ts",
65
- "import": "./dist/esm/app-router/server/index.js",
66
- "require": "./dist/cjs/app-router/server/index.js"
66
+ "types": "./dist/types/server/index.d.ts",
67
+ "import": "./dist/esm/server/index.js",
68
+ "require": "./dist/cjs/server/index.js"
69
+ },
70
+ "./admin": {
71
+ "types": "./dist/types/app-router/admin/index.d.ts",
72
+ "import": "./dist/esm/app-router/admin/index.js",
73
+ "require": "./dist/cjs/app-router/admin/index.js"
67
74
  }
68
75
  },
69
76
  "dependencies": {
@@ -72,6 +79,7 @@
72
79
  "@radix-ui/react-slot": "^1.1.1",
73
80
  "class-variance-authority": "^0.7.1",
74
81
  "clsx": "^2.1.1",
82
+ "jose": "^5.9.6",
75
83
  "lucide-react": "^0.468.0",
76
84
  "tailwind-merge": "^2.5.5",
77
85
  "tailwindcss-animate": "^1.0.7"
@@ -0,0 +1,5 @@
1
+ {
2
+ "main": "../dist/cjs/app-router/server/index.js",
3
+ "module": "../dist/esm/app-router/server/index.js",
4
+ "types": "../dist/types/app-router/server/index.d.ts"
5
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/auth.ts"],"sourcesContent":["'use server'\n\nimport { cookies } from 'next/headers';\nimport { verifyTernIdToken, verifyTernSessionCookie } from './sessionTernSecure';\n\nexport interface AuthResult {\n userId: string | null;\n token: string | null;\n error: Error | null;\n}\n\nexport async function auth(): Promise<AuthResult> {\n try {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\n if (sessionCookie) {\n const sessionResult = await verifyTernSessionCookie(sessionCookie);\n if (sessionResult.valid) {\n return {\n userId: sessionResult.uid,\n token: sessionCookie,\n error: null\n };\n }\n }\n\n // If session cookie is not present or invalid, try the ID token\n const idToken = cookieStore.get('_session_token')?.value;\n if (idToken) {\n const tokenResult = await verifyTernIdToken(idToken);\n if (tokenResult.valid) {\n return {\n userId: tokenResult.uid ?? null,\n token: idToken,\n error: null\n };\n }\n }\n\n /// If both checks fail, return null values\n return {\n userId: null,\n token: null,\n error: new Error('No valid session or token found')\n };\n } catch (error) {\n console.error('Error in auth function:', error);\n return {\n userId: null,\n token: null,\n error: error instanceof Error ? error : new Error('An unknown error occurred')\n };\n }\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,qBAAwB;AACxB,+BAA4D;AAQ5D,eAAsB,OAA4B;AAXlD;AAYE,MAAI;AACF,UAAM,cAAc,UAAM,wBAAQ;AAClC,UAAM,iBAAgB,iBAAY,IAAI,iBAAiB,MAAjC,mBAAoC;AAC1D,QAAI,eAAe;AACjB,YAAM,gBAAgB,UAAM,kDAAwB,aAAa;AACjE,UAAI,cAAc,OAAO;AACvB,eAAO;AAAA,UACL,QAAQ,cAAc;AAAA,UACtB,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAGA,UAAM,WAAU,iBAAY,IAAI,gBAAgB,MAAhC,mBAAmC;AACnD,QAAI,SAAS;AACX,YAAM,cAAc,UAAM,4CAAkB,OAAO;AACnD,UAAI,YAAY,OAAO;AACrB,eAAO;AAAA,UACL,SAAQ,iBAAY,QAAZ,YAAmB;AAAA,UAC3B,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO,IAAI,MAAM,iCAAiC;AAAA,IACpD;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,2BAA2B,KAAK;AAC9C,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,2BAA2B;AAAA,IAC/E;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/index.ts"],"sourcesContent":["export { adminTernSecureAuth, adminTernSecureDb } from '../../utils/admin-init'\nexport { ternSecureMiddleware } from './ternSecureMiddleware'\nexport { verifyTernSessionCookie, createSessionCookie } from './sessionTernSecure'\nexport { auth } from './auth'"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAuD;AACvD,kCAAqC;AACrC,+BAA6D;AAC7D,kBAAqB;","names":[]}
@@ -1 +0,0 @@
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"]}