@tern-secure/nextjs 3.2.42 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +34 -0
  2. package/dist/cjs/app-router/client/TernSecureProvider.js +1 -1
  3. package/dist/cjs/app-router/client/TernSecureProvider.js.map +1 -1
  4. package/dist/cjs/app-router/client/actions.js +52 -2
  5. package/dist/cjs/app-router/client/actions.js.map +1 -1
  6. package/dist/cjs/app-router/server/auth.js.map +1 -1
  7. package/dist/cjs/app-router/server/sessionTernSecure.js +21 -1
  8. package/dist/cjs/app-router/server/sessionTernSecure.js.map +1 -1
  9. package/dist/cjs/boundary/TernSecureClientProvider.js +0 -1
  10. package/dist/cjs/boundary/TernSecureClientProvider.js.map +1 -1
  11. package/dist/cjs/components/background.js +65 -0
  12. package/dist/cjs/components/background.js.map +1 -0
  13. package/dist/cjs/components/sign-in.js +166 -56
  14. package/dist/cjs/components/sign-in.js.map +1 -1
  15. package/dist/cjs/components/sign-out.js +69 -0
  16. package/dist/cjs/components/sign-out.js.map +1 -0
  17. package/dist/cjs/components/ui/alert.js +88 -0
  18. package/dist/cjs/components/ui/alert.js.map +1 -0
  19. package/dist/cjs/components/ui/button.js +84 -0
  20. package/dist/cjs/components/ui/button.js.map +1 -0
  21. package/dist/cjs/components/ui/card.js +101 -0
  22. package/dist/cjs/components/ui/card.js.map +1 -0
  23. package/dist/cjs/components/ui/input.js +58 -0
  24. package/dist/cjs/components/ui/input.js.map +1 -0
  25. package/dist/cjs/components/ui/label.js +55 -0
  26. package/dist/cjs/components/ui/label.js.map +1 -0
  27. package/dist/cjs/components/ui/separator.js +59 -0
  28. package/dist/cjs/components/ui/separator.js.map +1 -0
  29. package/dist/cjs/index.js +6 -3
  30. package/dist/cjs/index.js.map +1 -1
  31. package/dist/cjs/lib/utils.d.js +17 -0
  32. package/dist/cjs/lib/utils.d.js.map +1 -0
  33. package/dist/cjs/lib/utils.js +33 -0
  34. package/dist/cjs/lib/utils.js.map +1 -0
  35. package/dist/cjs/utils/client-init.js +2 -1
  36. package/dist/cjs/utils/client-init.js.map +1 -1
  37. package/dist/cjs/utils/construct.js +63 -0
  38. package/dist/cjs/utils/construct.js.map +1 -0
  39. package/dist/esm/app-router/client/TernSecureProvider.js +1 -1
  40. package/dist/esm/app-router/client/TernSecureProvider.js.map +1 -1
  41. package/dist/esm/app-router/client/actions.js +49 -2
  42. package/dist/esm/app-router/client/actions.js.map +1 -1
  43. package/dist/esm/app-router/server/auth.js.map +1 -1
  44. package/dist/esm/app-router/server/sessionTernSecure.js +20 -1
  45. package/dist/esm/app-router/server/sessionTernSecure.js.map +1 -1
  46. package/dist/esm/boundary/TernSecureClientProvider.js +0 -1
  47. package/dist/esm/boundary/TernSecureClientProvider.js.map +1 -1
  48. package/dist/esm/components/background.js +41 -0
  49. package/dist/esm/components/background.js.map +1 -0
  50. package/dist/esm/components/sign-in.js +164 -54
  51. package/dist/esm/components/sign-in.js.map +1 -1
  52. package/dist/esm/components/sign-out.js +45 -0
  53. package/dist/esm/components/sign-out.js.map +1 -0
  54. package/dist/esm/components/ui/alert.js +52 -0
  55. package/dist/esm/components/ui/alert.js.map +1 -0
  56. package/dist/esm/components/ui/button.js +49 -0
  57. package/dist/esm/components/ui/button.js.map +1 -0
  58. package/dist/esm/components/ui/card.js +62 -0
  59. package/dist/esm/components/ui/card.js.map +1 -0
  60. package/dist/esm/components/ui/input.js +24 -0
  61. package/dist/esm/components/ui/input.js.map +1 -0
  62. package/dist/esm/components/ui/label.js +21 -0
  63. package/dist/esm/components/ui/label.js.map +1 -0
  64. package/dist/esm/components/ui/separator.js +25 -0
  65. package/dist/esm/components/ui/separator.js.map +1 -0
  66. package/dist/esm/index.js +2 -0
  67. package/dist/esm/index.js.map +1 -1
  68. package/dist/esm/lib/utils.d.js +1 -0
  69. package/dist/esm/lib/utils.d.js.map +1 -0
  70. package/dist/esm/lib/utils.js +9 -0
  71. package/dist/esm/lib/utils.js.map +1 -0
  72. package/dist/esm/utils/client-init.js +2 -1
  73. package/dist/esm/utils/client-init.js.map +1 -1
  74. package/dist/esm/utils/construct.js +37 -0
  75. package/dist/esm/utils/construct.js.map +1 -0
  76. package/dist/types/app-router/client/TernSecureProvider.d.ts +2 -2
  77. package/dist/types/app-router/client/TernSecureProvider.d.ts.map +1 -1
  78. package/dist/types/app-router/client/actions.d.ts +34 -0
  79. package/dist/types/app-router/client/actions.d.ts.map +1 -1
  80. package/dist/types/app-router/server/sessionTernSecure.d.ts +4 -0
  81. package/dist/types/app-router/server/sessionTernSecure.d.ts.map +1 -1
  82. package/dist/types/boundary/TernSecureClientProvider.d.ts.map +1 -1
  83. package/dist/types/components/background.d.ts +2 -0
  84. package/dist/types/components/background.d.ts.map +1 -0
  85. package/dist/types/components/sign-in.d.ts +8 -10
  86. package/dist/types/components/sign-in.d.ts.map +1 -1
  87. package/dist/types/components/sign-out.d.ts +10 -0
  88. package/dist/types/components/sign-out.d.ts.map +1 -0
  89. package/dist/types/components/ui/alert.d.ts +9 -0
  90. package/dist/types/components/ui/alert.d.ts.map +1 -0
  91. package/dist/types/components/ui/button.d.ts +12 -0
  92. package/dist/types/components/ui/button.d.ts.map +1 -0
  93. package/dist/types/components/ui/card.d.ts +9 -0
  94. package/dist/types/components/ui/card.d.ts.map +1 -0
  95. package/dist/types/components/ui/input.d.ts +4 -0
  96. package/dist/types/components/ui/input.d.ts.map +1 -0
  97. package/dist/types/components/ui/label.d.ts +6 -0
  98. package/dist/types/components/ui/label.d.ts.map +1 -0
  99. package/dist/types/components/ui/separator.d.ts +5 -0
  100. package/dist/types/components/ui/separator.d.ts.map +1 -0
  101. package/dist/types/index.d.ts +1 -0
  102. package/dist/types/index.d.ts.map +1 -1
  103. package/dist/types/lib/utils.d.ts +3 -0
  104. package/dist/types/lib/utils.d.ts.map +1 -0
  105. package/dist/types/utils/client-init.d.ts +2 -2
  106. package/dist/types/utils/client-init.d.ts.map +1 -1
  107. package/dist/types/utils/construct.d.ts +22 -0
  108. package/dist/types/utils/construct.d.ts.map +1 -0
  109. package/package.json +79 -65
package/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # @tern-secure/nextjs
2
+
3
+ A comprehensive Firebase authentication solution for Next.js applications, providing seamless integration with Firebase Auth, including email/password, Google, and Microsoft authentication methods.
4
+
5
+ [![npm version](https://badge.fury.io/js/@tern-secure%2Fnextjs.svg)](https://www.npmjs.com/package/@tern-secure/nextjs)
6
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
7
+
8
+ ## Features
9
+
10
+ - 🔐 Multiple authentication methods:
11
+ - Email/Password authentication
12
+ - Google OAuth
13
+ - Microsoft OAuth
14
+ - 🔄 Session management with cookies
15
+ - ⚡ Server-side and client-side components
16
+ - 🎨 Customizable UI components
17
+ - 📦 TypeScript support
18
+ - 🚀 Next.js App Router compatible
19
+
20
+ ## Installation
21
+
22
+ ## Environment Variables
23
+
24
+ Required environment variables:
25
+ ```
26
+ NEXT_PUBLIC_FIREBASE_API_KEY=
27
+ NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
28
+ NEXT_PUBLIC_FIREBASE_PROJECT_ID=
29
+ NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
30
+ NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
31
+ NEXT_PUBLIC_FIREBASE_APP_ID=
32
+ FIREBASE_ADMIN_CLIENT_EMAIL=
33
+ FIREBASE_ADMIN_PRIVATE_KEY=
34
+ ```
@@ -23,7 +23,7 @@ __export(TernSecureProvider_exports, {
23
23
  module.exports = __toCommonJS(TernSecureProvider_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_TernSecureClientProvider = require("../../boundary/TernSecureClientProvider");
26
- function TernSecureProvider({ children }) {
26
+ async function TernSecureProvider({ children }) {
27
27
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TernSecureClientProvider.TernSecureClientProvider, { children });
28
28
  }
29
29
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/client/TernSecureProvider.tsx"],"sourcesContent":["import React from \"react\"\r\nimport { TernSecureClientProvider } from \"../../boundary/TernSecureClientProvider\"\r\n\r\n\r\n// Loading fallback component\r\n/*function TernSecureLoadingFallback() {\r\n return (\r\n <div>\r\n <span className=\"sr-only\">Loading...</span>\r\n </div>\r\n )\r\n}*/\r\n/**\r\n * Root Provider for TernSecure\r\n * Use this in your Next.js App Router root layout\r\n * Automatically handles client/server boundary and authentication state\r\n * \r\n * @example\r\n * // app/layout.tsx\r\n * import { TernSecureProvider } from '@tern/secure'\r\n * \r\n * export default function RootLayout({ children }) {\r\n * return (\r\n * <html>\r\n * <body>\r\n * <TernSecureProvider>\r\n * {children}\r\n * </TernSecureProvider>\r\n * </body>\r\n * </html>\r\n * )\r\n * }\r\n */\r\nexport function TernSecureProvider({ children }: { children: React.ReactNode }) {\r\n return (\r\n <TernSecureClientProvider>\r\n {children}\r\n </TernSecureClientProvider>\r\n )\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCI;AAlCJ,sCAAyC;AAgClC,SAAS,mBAAmB,EAAE,SAAS,GAAkC;AAC9E,SACE,4CAAC,4DACI,UACL;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/client/TernSecureProvider.tsx"],"sourcesContent":["import React from \"react\"\r\nimport { TernSecureClientProvider } from \"../../boundary/TernSecureClientProvider\"\r\n\r\n\r\n// Loading fallback component\r\n/*function TernSecureLoadingFallback() {\r\n return (\r\n <div>\r\n <span className=\"sr-only\">Loading...</span>\r\n </div>\r\n )\r\n}*/\r\n/**\r\n * Root Provider for TernSecure\r\n * Use this in your Next.js App Router root layout\r\n * Automatically handles client/server boundary and authentication state\r\n * \r\n * @example\r\n * /// app/layout.tsx\r\n * import { TernSecureProvider } from '@tern/secure'\r\n * \r\n * export default function RootLayout({ children }) {\r\n * return (\r\n * <html>\r\n * <body>\r\n * <TernSecureProvider>\r\n * {children}\r\n * </TernSecureProvider>\r\n * </body>\r\n * </html>\r\n * )\r\n * }\r\n */\r\nexport async function TernSecureProvider({ children }: { children: React.ReactNode }) {\r\n return (\r\n <TernSecureClientProvider>\r\n {children}\r\n </TernSecureClientProvider>\r\n )\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCI;AAlCJ,sCAAyC;AAgCzC,eAAsB,mBAAmB,EAAE,SAAS,GAAkC;AACpF,SACE,4CAAC,4DACI,UACL;AAEJ;","names":[]}
@@ -18,7 +18,10 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var actions_exports = {};
20
20
  __export(actions_exports, {
21
- signInWithEmail: () => signInWithEmail
21
+ handleAuthRedirectResult: () => handleAuthRedirectResult,
22
+ signInWithEmail: () => signInWithEmail,
23
+ signInWithMicrosoft: () => signInWithMicrosoft,
24
+ signInWithRedirectGoogle: () => signInWithRedirectGoogle
22
25
  });
23
26
  module.exports = __toCommonJS(actions_exports);
24
27
  var import_client_init = require("../../utils/client-init");
@@ -40,8 +43,55 @@ async function signInWithEmail(email, password) {
40
43
  throw new Error(errorMessage);
41
44
  }
42
45
  }
46
+ async function signInWithRedirectGoogle() {
47
+ const auth = (0, import_client_init.TernSecureAuth)();
48
+ const provider = new import_auth.GoogleAuthProvider();
49
+ provider.setCustomParameters({
50
+ login_hint: "user@example.com",
51
+ prompt: "select_account"
52
+ });
53
+ try {
54
+ await (0, import_auth.signInWithRedirect)(auth, provider);
55
+ return { success: true, message: "Redirect initiated" };
56
+ } catch (error) {
57
+ console.error("Error during Google sign-in:", error);
58
+ return { success: false, error: "Failed to sign in with Google" };
59
+ }
60
+ }
61
+ async function signInWithMicrosoft() {
62
+ const auth = (0, import_client_init.TernSecureAuth)();
63
+ const provider = new import_auth.OAuthProvider("microsoft.com");
64
+ provider.setCustomParameters({
65
+ prompt: "consent"
66
+ });
67
+ try {
68
+ await (0, import_auth.signInWithRedirect)(auth, provider);
69
+ return { success: true, message: "Redirect initiated" };
70
+ } catch (error) {
71
+ console.error("Error during Google sign-in:", error);
72
+ return { success: false, error: "Failed to sign in with Google" };
73
+ }
74
+ }
75
+ async function handleAuthRedirectResult() {
76
+ const auth = (0, import_client_init.TernSecureAuth)();
77
+ try {
78
+ const result = await (0, import_auth.getRedirectResult)(auth);
79
+ if (result) {
80
+ const user = result.user;
81
+ return { success: true, user };
82
+ } else {
83
+ return { success: false, error: "No redirect result" };
84
+ }
85
+ } catch (error) {
86
+ console.error("Error handling auth redirect result:", error);
87
+ return { success: false, error: error.message || "Failed to handle auth redirect", code: error.code };
88
+ }
89
+ }
43
90
  // Annotate the CommonJS export names for ESM import in node:
44
91
  0 && (module.exports = {
45
- signInWithEmail
92
+ handleAuthRedirectResult,
93
+ signInWithEmail,
94
+ signInWithMicrosoft,
95
+ signInWithRedirectGoogle
46
96
  });
47
97
  //# sourceMappingURL=actions.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/client/actions.ts"],"sourcesContent":["import { TernSecureAuth } from '../../utils/client-init'\r\nimport { signInWithEmailAndPassword } from 'firebase/auth'\r\nimport { createSessionCookie } from '../server/sessionTernSecure'\r\n\r\n\r\nexport async function signInWithEmail(email: string, password: string){\r\n const auth = TernSecureAuth()\r\n try {\r\n const UserCredential = await signInWithEmailAndPassword(auth, email, password)\r\n const idToken = await UserCredential.user.getIdToken();\r\n\r\n const res = await createSessionCookie(idToken);\r\n\r\n if(res.success) {\r\n return { success: true, message: 'Connected.' };\r\n } else {\r\n throw new Error(res.message);\r\n }\r\n} catch (error){\r\n const errorMessage = error instanceof Error ? error.message : 'Failed to sign in';\r\n throw new Error(errorMessage);\r\n}\r\n} "],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA+B;AAC/B,kBAA2C;AAC3C,+BAAoC;AAGpC,eAAsB,gBAAgB,OAAe,UAAiB;AACpE,QAAM,WAAO,mCAAe;AAC5B,MAAI;AACJ,UAAM,iBAAiB,UAAM,wCAA2B,MAAM,OAAO,QAAQ;AAC7E,UAAM,UAAU,MAAM,eAAe,KAAK,WAAW;AAErD,UAAM,MAAM,UAAM,8CAAoB,OAAO;AAE7C,QAAG,IAAI,SAAS;AACd,aAAO,EAAE,SAAS,MAAM,SAAS,aAAa;AAAA,IAChD,OAAO;AACL,YAAM,IAAI,MAAM,IAAI,OAAO;AAAA,IAC7B;AAAA,EACF,SAAS,OAAM;AACb,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,UAAM,IAAI,MAAM,YAAY;AAAA,EAC9B;AACA;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/client/actions.ts"],"sourcesContent":["import { TernSecureAuth } from '../../utils/client-init'\r\nimport { signInWithEmailAndPassword, signInWithRedirect, getRedirectResult, GoogleAuthProvider, OAuthProvider } from 'firebase/auth'\r\nimport { createSessionCookie } from '../server/sessionTernSecure'\r\n\r\n\r\nexport async function signInWithEmail(email: string, password: string){\r\n const auth = TernSecureAuth()\r\n try {\r\n const UserCredential = await signInWithEmailAndPassword(auth, email, password)\r\n const idToken = await UserCredential.user.getIdToken();\r\n\r\n const res = await createSessionCookie(idToken);\r\n\r\n if(res.success) {\r\n return { success: true, message: 'Connected.' };\r\n } else {\r\n throw new Error(res.message);\r\n }\r\n} catch (error){\r\n const errorMessage = error instanceof Error ? error.message : 'Failed to sign in';\r\n throw new Error(errorMessage);\r\n}\r\n} \r\n\r\nexport async function signInWithRedirectGoogle() {\r\n const auth = TernSecureAuth()\r\n const provider = new GoogleAuthProvider()\r\n provider.setCustomParameters({\r\n login_hint: 'user@example.com',\r\n prompt: 'select_account'\r\n })\r\n\r\n try {\r\n await signInWithRedirect(auth, provider)\r\n return { success: true, message: 'Redirect initiated' }\r\n } catch (error) {\r\n console.error('Error during Google sign-in:', error)\r\n return { success: false, error: 'Failed to sign in with Google' }\r\n }\r\n}\r\n\r\n\r\nexport async function signInWithMicrosoft() {\r\n const auth = TernSecureAuth()\r\n const provider = new OAuthProvider('microsoft.com')\r\n provider.setCustomParameters({\r\n prompt: 'consent'\r\n })\r\n\r\n try {\r\n await signInWithRedirect(auth, provider)\r\n return { success: true, message: 'Redirect initiated' }\r\n } catch (error) {\r\n console.error('Error during Google sign-in:', error)\r\n return { success: false, error: 'Failed to sign in with Google' }\r\n }\r\n}\r\n\r\n\r\nexport async function handleAuthRedirectResult() {\r\n const auth = TernSecureAuth()\r\n try {\r\n const result = await getRedirectResult(auth)\r\n if (result) {\r\n const user = result.user\r\n return { success: true, user }\r\n } else {\r\n return { success: false, error: 'No redirect result' }\r\n }\r\n } catch (error: any) {\r\n console.error('Error handling auth redirect result:', error)\r\n return { success: false, error: error.message || 'Failed to handle auth redirect', code: error.code }\r\n }\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA+B;AAC/B,kBAAqH;AACrH,+BAAoC;AAGpC,eAAsB,gBAAgB,OAAe,UAAiB;AACpE,QAAM,WAAO,mCAAe;AAC5B,MAAI;AACJ,UAAM,iBAAiB,UAAM,wCAA2B,MAAM,OAAO,QAAQ;AAC7E,UAAM,UAAU,MAAM,eAAe,KAAK,WAAW;AAErD,UAAM,MAAM,UAAM,8CAAoB,OAAO;AAE7C,QAAG,IAAI,SAAS;AACd,aAAO,EAAE,SAAS,MAAM,SAAS,aAAa;AAAA,IAChD,OAAO;AACL,YAAM,IAAI,MAAM,IAAI,OAAO;AAAA,IAC7B;AAAA,EACF,SAAS,OAAM;AACb,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,UAAM,IAAI,MAAM,YAAY;AAAA,EAC9B;AACA;AAEA,eAAsB,2BAA2B;AAC/C,QAAM,WAAO,mCAAe;AAC5B,QAAM,WAAW,IAAI,+BAAmB;AACxC,WAAS,oBAAoB;AAAA,IAC3B,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV,CAAC;AAED,MAAI;AACF,cAAM,gCAAmB,MAAM,QAAQ;AACvC,WAAO,EAAE,SAAS,MAAM,SAAS,qBAAqB;AAAA,EACxD,SAAS,OAAO;AACd,YAAQ,MAAM,gCAAgC,KAAK;AACnD,WAAO,EAAE,SAAS,OAAO,OAAO,gCAAgC;AAAA,EAClE;AACF;AAGA,eAAsB,sBAAsB;AAC1C,QAAM,WAAO,mCAAe;AAC5B,QAAM,WAAW,IAAI,0BAAc,eAAe;AAClD,WAAS,oBAAoB;AAAA,IAC3B,QAAQ;AAAA,EACV,CAAC;AAED,MAAI;AACF,cAAM,gCAAmB,MAAM,QAAQ;AACvC,WAAO,EAAE,SAAS,MAAM,SAAS,qBAAqB;AAAA,EACxD,SAAS,OAAO;AACd,YAAQ,MAAM,gCAAgC,KAAK;AACnD,WAAO,EAAE,SAAS,OAAO,OAAO,gCAAgC;AAAA,EAClE;AACF;AAGA,eAAsB,2BAA2B;AAC/C,QAAM,WAAO,mCAAe;AAC5B,MAAI;AACF,UAAM,SAAS,UAAM,+BAAkB,IAAI;AAC3C,QAAI,QAAQ;AACV,YAAM,OAAO,OAAO;AACpB,aAAO,EAAE,SAAS,MAAM,KAAK;AAAA,IAC/B,OAAO;AACL,aAAO,EAAE,SAAS,OAAO,OAAO,qBAAqB;AAAA,IACvD;AAAA,EACF,SAAS,OAAY;AACnB,YAAQ,MAAM,wCAAwC,KAAK;AAC3D,WAAO,EAAE,SAAS,OAAO,OAAO,MAAM,WAAW,kCAAkC,MAAM,MAAM,KAAK;AAAA,EACtG;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/auth.ts"],"sourcesContent":["'use server'\r\n\r\nimport { cookies } from 'next/headers';\r\nimport { verifyTernIdToken, verifyTernSessionCookie } from './sessionTernSecure';\r\n\r\nexport interface AuthResult {\r\n userId: string | null;\r\n token: string | null;\r\n error: Error | null;\r\n}\r\n\r\nexport async function auth(): Promise<AuthResult> {\r\n try {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\r\n if (sessionCookie) {\r\n const sessionResult = await verifyTernSessionCookie(sessionCookie);\r\n if (sessionResult.valid) {\r\n return {\r\n userId: sessionResult.uid,\r\n token: sessionCookie,\r\n error: null\r\n };\r\n }\r\n }\r\n\r\n // If session cookie is not present or invalid, try the ID token\r\n const idToken = cookieStore.get('_session_token')?.value;\r\n if (idToken) {\r\n const tokenResult = await verifyTernIdToken(idToken);\r\n if (tokenResult.valid) {\r\n return {\r\n userId: tokenResult.uid ?? null,\r\n token: idToken,\r\n error: null\r\n };\r\n }\r\n }\r\n\r\n // If both checks fail, return null values\r\n return {\r\n userId: null,\r\n token: null,\r\n error: new Error('No valid session or token found')\r\n };\r\n } catch (error) {\r\n console.error('Error in auth function:', error);\r\n return {\r\n userId: null,\r\n token: null,\r\n error: error instanceof Error ? error : new Error('An unknown error occurred')\r\n };\r\n }\r\n}\r\n\r\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
+ {"version":3,"sources":["../../../../src/app-router/server/auth.ts"],"sourcesContent":["'use server'\r\n\r\nimport { cookies } from 'next/headers';\r\nimport { verifyTernIdToken, verifyTernSessionCookie } from './sessionTernSecure';\r\n\r\nexport interface AuthResult {\r\n userId: string | null;\r\n token: string | null;\r\n error: Error | null;\r\n}\r\n\r\nexport async function auth(): Promise<AuthResult> {\r\n try {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\r\n if (sessionCookie) {\r\n const sessionResult = await verifyTernSessionCookie(sessionCookie);\r\n if (sessionResult.valid) {\r\n return {\r\n userId: sessionResult.uid,\r\n token: sessionCookie,\r\n error: null\r\n };\r\n }\r\n }\r\n\r\n // If session cookie is not present or invalid, try the ID token\r\n const idToken = cookieStore.get('_session_token')?.value;\r\n if (idToken) {\r\n const tokenResult = await verifyTernIdToken(idToken);\r\n if (tokenResult.valid) {\r\n return {\r\n userId: tokenResult.uid ?? null,\r\n token: idToken,\r\n error: null\r\n };\r\n }\r\n }\r\n\r\n /// If both checks fail, return null values\r\n return {\r\n userId: null,\r\n token: null,\r\n error: new Error('No valid session or token found')\r\n };\r\n } catch (error) {\r\n console.error('Error in auth function:', error);\r\n return {\r\n userId: null,\r\n token: null,\r\n error: error instanceof Error ? error : new Error('An unknown error occurred')\r\n };\r\n }\r\n}\r\n\r\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":[]}
@@ -19,6 +19,7 @@ var __copyProps = (to, from, except, desc) => {
19
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
20
  var sessionTernSecure_exports = {};
21
21
  __export(sessionTernSecure_exports, {
22
+ clearSessionCookie: () => clearSessionCookie,
22
23
  createSessionCookie: () => createSessionCookie,
23
24
  getIdToken: () => getIdToken,
24
25
  getServerSessionCookie: () => getServerSessionCookie,
@@ -94,7 +95,7 @@ async function setServerSession(token) {
94
95
  }
95
96
  async function verifyTernIdToken(token) {
96
97
  try {
97
- const decodedToken = await import_admin_init.adminTernSecureAuth.verifyIdToken(token);
98
+ const decodedToken = await import_admin_init.adminTernSecureAuth.verifyIdToken(token, true);
98
99
  return { valid: true, uid: decodedToken.uid };
99
100
  } catch (error) {
100
101
  if (error instanceof Error) {
@@ -127,8 +128,27 @@ async function verifyTernSessionCookie(session) {
127
128
  return { error, valid: false };
128
129
  }
129
130
  }
131
+ async function clearSessionCookie() {
132
+ var _a;
133
+ const cookieStore = await (0, import_headers.cookies)();
134
+ cookieStore.delete("_session_cookie");
135
+ cookieStore.delete("_session_token");
136
+ cookieStore.delete("_session");
137
+ try {
138
+ const sessionCookie = (_a = cookieStore.get("_session_cookie")) == null ? void 0 : _a.value;
139
+ if (sessionCookie) {
140
+ const decodedClaims = await import_admin_init.adminTernSecureAuth.verifySessionCookie(sessionCookie);
141
+ await import_admin_init.adminTernSecureAuth.revokeRefreshTokens(decodedClaims.uid);
142
+ }
143
+ return { success: true, message: "Session cleared successfully" };
144
+ } catch (error) {
145
+ console.error("Error clearing session:", error);
146
+ return { success: true, message: "Session cookies cleared" };
147
+ }
148
+ }
130
149
  // Annotate the CommonJS export names for ESM import in node:
131
150
  0 && (module.exports = {
151
+ clearSessionCookie,
132
152
  createSessionCookie,
133
153
  getIdToken,
134
154
  getServerSessionCookie,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/sessionTernSecure.ts"],"sourcesContent":["'use server'\r\n\r\nimport { cookies } from 'next/headers';\r\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\r\n\r\ninterface FirebaseAuthError extends Error {\r\n code?: string;\r\n}\r\n\r\nexport interface User {\r\n uid: string | null;\r\n email: string | null;\r\n }\r\n\r\nexport interface Session {\r\n user: User | null;\r\n token: string | null;\r\n error: Error | null;\r\n}\r\n\r\nexport async function createSessionCookie(idToken: string) {\r\n try {\r\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\r\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\r\n\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session_cookie', sessionCookie, {\r\n maxAge: expiresIn,\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n path: '/',\r\n });\r\n return { success: true, message: 'Session created' };\r\n } catch (error) {\r\n return { success: false, message: 'Failed to create session' };\r\n }\r\n}\r\n\r\n\r\n\r\nexport async function getServerSessionCookie() {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\r\n\r\n if (!sessionCookie) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return {\r\n token: sessionCookie,\r\n userId: decondeClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\n\r\nexport async function getIdToken() {\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get('_session_token')?.value;\r\n\r\n if (!token) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifyIdToken(token)\r\n return {\r\n token: token,\r\n userId: decodedClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\nexport async function setServerSession(token: string) {\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session', token, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: 60 * 60, // 1 hour\r\n path: '/',\r\n });\r\n }\r\n\r\n export async function verifyTernIdToken(token: string): Promise<{ valid: boolean; uid?: string; error?: string }> {\r\n try {\r\n const decodedToken = await adminAuth.verifyIdToken(token);\r\n return { valid: true, uid: decodedToken.uid };\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n const firebaseError = error as FirebaseAuthError;\r\n if (error.name === 'FirebaseAuthError') {\r\n // Handle specific Firebase Auth errors\r\n switch (firebaseError.code) {\r\n case 'auth/id-token-expired':\r\n return { valid: false, error: 'Token has expired' };\r\n case 'auth/id-token-revoked':\r\n return { valid: false, error: 'Token has been revoked' };\r\n case 'auth/user-disabled':\r\n return { valid: false, error: 'User account has been disabled' };\r\n default:\r\n return { valid: false, error: 'Invalid token' };\r\n }\r\n }\r\n }\r\n return { valid: false, error: 'Error verifying token' };\r\n }\r\n }\r\n \r\n\r\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifySessionCookie(session, true);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid session'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n\r\n\r\n/*\r\n export async function GET(request: NextRequest) {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('session')?.value\r\n \r\n if (!sessionCookie) {\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\r\n } catch (error) {\r\n console.error('Error verifying session cookie:', error)\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n }\r\n\r\n*/"],"mappings":"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","names":["adminAuth"]}
1
+ {"version":3,"sources":["../../../../src/app-router/server/sessionTernSecure.ts"],"sourcesContent":["'use server'\r\n\r\nimport { cookies } from 'next/headers';\r\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\r\n\r\ninterface FirebaseAuthError extends Error {\r\n code?: string;\r\n}\r\n\r\nexport interface User {\r\n uid: string | null;\r\n email: string | null;\r\n }\r\n\r\nexport interface Session {\r\n user: User | null;\r\n token: string | null;\r\n error: Error | null;\r\n}\r\n\r\nexport async function createSessionCookie(idToken: string) {\r\n try {\r\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\r\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\r\n\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session_cookie', sessionCookie, {\r\n maxAge: expiresIn,\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n path: '/',\r\n });\r\n return { success: true, message: 'Session created' };\r\n } catch (error) {\r\n return { success: false, message: 'Failed to create session' };\r\n }\r\n}\r\n\r\n\r\n\r\nexport async function getServerSessionCookie() {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\r\n\r\n if (!sessionCookie) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return {\r\n token: sessionCookie,\r\n userId: decondeClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\n\r\nexport async function getIdToken() {\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get('_session_token')?.value;\r\n\r\n if (!token) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifyIdToken(token)\r\n return {\r\n token: token,\r\n userId: decodedClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\nexport async function setServerSession(token: string) {\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session', token, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: 60 * 60, // 1 hour\r\n path: '/',\r\n });\r\n }\r\n\r\n export async function verifyTernIdToken(token: string): Promise<{ valid: boolean; uid?: string; error?: string }> {\r\n try {\r\n const decodedToken = await adminAuth.verifyIdToken(token, true);\r\n return { valid: true, uid: decodedToken.uid };\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n const firebaseError = error as FirebaseAuthError;\r\n if (error.name === 'FirebaseAuthError') {\r\n // Handle specific Firebase Auth errors\r\n switch (firebaseError.code) {\r\n case 'auth/id-token-expired':\r\n return { valid: false, error: 'Token has expired' };\r\n case 'auth/id-token-revoked':\r\n return { valid: false, error: 'Token has been revoked' };\r\n case 'auth/user-disabled':\r\n return { valid: false, error: 'User account has been disabled' };\r\n default:\r\n return { valid: false, error: 'Invalid token' };\r\n }\r\n }\r\n }\r\n return { valid: false, error: 'Error verifying token' };\r\n }\r\n }\r\n \r\n\r\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifySessionCookie(session, true);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid session'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n\r\n export async function clearSessionCookie() {\r\n const cookieStore = await cookies()\r\n \r\n cookieStore.delete('_session_cookie')\r\n cookieStore.delete('_session_token')\r\n cookieStore.delete('_session')\r\n \r\n try {\r\n // Verify if there's an active session before revoking\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value\r\n if (sessionCookie) {\r\n // Get the decoded claims to get the user's ID\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie)\r\n \r\n // Revoke all sessions for the user\r\n await adminAuth.revokeRefreshTokens(decodedClaims.uid)\r\n }\r\n \r\n return { success: true, message: 'Session cleared successfully' }\r\n } catch (error) {\r\n console.error('Error clearing session:', error)\r\n // Still return success even if revoking fails, as cookies are cleared\r\n return { success: true, message: 'Session cookies cleared' }\r\n }\r\n }\r\n\r\n\r\n\r\n/*\r\n export async function GET(request: NextRequest) {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('session')?.value\r\n \r\n if (!sessionCookie) {\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\r\n } catch (error) {\r\n console.error('Error verifying session cookie:', error)\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n }\r\n\r\n*/"],"mappings":"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","names":["adminAuth"]}
@@ -56,7 +56,6 @@ function TernSecureClientProvider({
56
56
  (0, import_react.useEffect)(() => {
57
57
  const unsubscribe = (0, import_auth.onAuthStateChanged)(auth, async (user) => {
58
58
  if (user) {
59
- await user.getIdToken();
60
59
  setAuthState({
61
60
  isLoaded: true,
62
61
  userId: user.uid,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { onAuthStateChanged, User } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureCtxValue, TernSecureState } from './TernSecureCtx'\r\nimport { useRouter } from 'next/navigation'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n loginPath?: string;\r\n loadingComponent?: React.ReactNode;\r\n}\r\n\r\nexport function TernSecureClientProvider({ \r\n children, \r\n loginPath = '/sign-in',\r\n loadingComponent\r\n}: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n const router = useRouter();\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n isValid: false,\r\n token: null\r\n }));\r\n\r\n const handleSignOut = useCallback(async (error?: Error) => {\r\n await auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error || null,\r\n isValid: false,\r\n token: null\r\n });\r\n router.push(loginPath);\r\n }, [auth, router, loginPath]);\r\n\r\nuseEffect(() => {\r\n const unsubscribe = onAuthStateChanged(auth, async (user: User | null) => {\r\n if (user) {\r\n await user.getIdToken()\r\n setAuthState({\r\n isLoaded: true,\r\n userId: user.uid,\r\n isValid: true,\r\n token: user.getIdToken(),\r\n error: null\r\n })\r\n } else {\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n isValid: false,\r\n token: null,\r\n error: new Error('User is not authenticated')\r\n })\r\n router.push(loginPath);\r\n }\r\n }, (error) => {\r\n handleSignOut(error instanceof Error ? error : new Error('Authentication error occurred'));\r\n })\r\n \r\n return () => unsubscribe()\r\n }, [auth, handleSignOut, router, loginPath])\r\n\r\n const contextValue: TernSecureCtxValue = useMemo(() => ({\r\n ...authState,\r\n signOut: handleSignOut,\r\n }), [authState, auth, handleSignOut]);\r\n\r\n if (!authState.isLoaded) {\r\n return (\r\n <TernSecureCtx.Provider value={contextValue}>\r\n {loadingComponent || (\r\n <div aria-live=\"polite\" aria-busy=\"true\">\r\n <span className=\"sr-only\">Loading authentication state...</span>\r\n </div>\r\n )}\r\n </TernSecureCtx.Provider>\r\n );\r\n }\r\n\r\n return (\r\n <TernSecureCtx.Provider value={contextValue}>\r\n {children}\r\n </TernSecureCtx.Provider>\r\n )\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgFY;AA9EZ,mBAAiE;AACjE,yBAA+B;AAC/B,kBAAyC;AACzC,2BAAmE;AACnE,wBAA0B;AASnB,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA,YAAY;AAAA,EACZ;AACF,GAAkC;AAChC,QAAM,WAAO,sBAAQ,MAAM,mCAAgB,CAAC,CAAC;AAC7C,QAAM,aAAS,6BAAU;AACzB,QAAM,CAAC,WAAW,YAAY,QAAI,uBAA0B,OAAO;AAAA,IACjE,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACT,EAAE;AAEF,QAAM,oBAAgB,0BAAY,OAAO,UAAkB;AACzD,UAAM,KAAK,QAAQ;AACnB,iBAAa;AAAA,MACX,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,OAAO;AAAA,IACT,CAAC;AACD,WAAO,KAAK,SAAS;AAAA,EACvB,GAAG,CAAC,MAAM,QAAQ,SAAS,CAAC;AAE9B,8BAAU,MAAM;AACZ,UAAM,kBAAc,gCAAmB,MAAM,OAAO,SAAsB;AACxE,UAAI,MAAM;AACR,cAAM,KAAK,WAAW;AACtB,qBAAa;AAAA,UACX,UAAU;AAAA,UACV,QAAQ,KAAK;AAAA,UACb,SAAS;AAAA,UACT,OAAO,KAAK,WAAW;AAAA,UACvB,OAAO;AAAA,QACT,CAAC;AAAA,MACH,OAAO;AACL,qBAAa;AAAA,UACX,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,OAAO;AAAA,UACP,OAAO,IAAI,MAAM,2BAA2B;AAAA,QAC9C,CAAC;AACD,eAAO,KAAK,SAAS;AAAA,MACvB;AAAA,IACF,GAAG,CAAC,UAAU;AACZ,oBAAc,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,+BAA+B,CAAC;AAAA,IAC3F,CAAC;AAED,WAAO,MAAM,YAAY;AAAA,EAC3B,GAAG,CAAC,MAAM,eAAe,QAAQ,SAAS,CAAC;AAE3C,QAAM,mBAAmC,sBAAQ,OAAO;AAAA,IACtD,GAAG;AAAA,IACH,SAAS;AAAA,EACX,IAAI,CAAC,WAAW,MAAM,aAAa,CAAC;AAEpC,MAAI,CAAC,UAAU,UAAU;AACvB,WACE,4CAAC,mCAAc,UAAd,EAAuB,OAAO,cAC5B,8BACC,4CAAC,SAAI,aAAU,UAAS,aAAU,QAChC,sDAAC,UAAK,WAAU,WAAU,6CAA+B,GAC3D,GAEJ;AAAA,EAEJ;AAEA,SACI,4CAAC,mCAAc,UAAd,EAAuB,OAAO,cAC7B,UACF;AAEN;","names":[]}
1
+ {"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { onAuthStateChanged, User } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureCtxValue, TernSecureState } from './TernSecureCtx'\r\nimport { useRouter } from 'next/navigation'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n loginPath?: string;\r\n loadingComponent?: React.ReactNode;\r\n}\r\n\r\nexport function TernSecureClientProvider({ \r\n children, \r\n loginPath = '/sign-in',\r\n loadingComponent\r\n}: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n const router = useRouter();\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n isValid: false,\r\n token: null\r\n }));\r\n\r\n const handleSignOut = useCallback(async (error?: Error) => {\r\n await auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error || null,\r\n isValid: false,\r\n token: null\r\n });\r\n router.push(loginPath);\r\n }, [auth, router, loginPath]);\r\n\r\nuseEffect(() => {\r\n const unsubscribe = onAuthStateChanged(auth, async (user: User | null) => {\r\n if (user) {\r\n setAuthState({\r\n isLoaded: true,\r\n userId: user.uid,\r\n isValid: true,\r\n token: user.getIdToken(),\r\n error: null\r\n })\r\n } else {\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n isValid: false,\r\n token: null,\r\n error: new Error('User is not authenticated')\r\n })\r\n router.push(loginPath);\r\n }\r\n }, (error) => {\r\n handleSignOut(error instanceof Error ? error : new Error('Authentication error occurred'));\r\n })\r\n \r\n return () => unsubscribe()\r\n }, [auth, handleSignOut, router, loginPath])\r\n\r\n const contextValue: TernSecureCtxValue = useMemo(() => ({\r\n ...authState,\r\n signOut: handleSignOut,\r\n }), [authState, auth, handleSignOut]);\r\n\r\n if (!authState.isLoaded) {\r\n return (\r\n <TernSecureCtx.Provider value={contextValue}>\r\n {loadingComponent || (\r\n <div aria-live=\"polite\" aria-busy=\"true\">\r\n <span className=\"sr-only\">Loading authentication state...</span>\r\n </div>\r\n )}\r\n </TernSecureCtx.Provider>\r\n );\r\n }\r\n\r\n return (\r\n <TernSecureCtx.Provider value={contextValue}>\r\n {children}\r\n </TernSecureCtx.Provider>\r\n )\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+EY;AA7EZ,mBAAiE;AACjE,yBAA+B;AAC/B,kBAAyC;AACzC,2BAAmE;AACnE,wBAA0B;AASnB,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA,YAAY;AAAA,EACZ;AACF,GAAkC;AAChC,QAAM,WAAO,sBAAQ,MAAM,mCAAgB,CAAC,CAAC;AAC7C,QAAM,aAAS,6BAAU;AACzB,QAAM,CAAC,WAAW,YAAY,QAAI,uBAA0B,OAAO;AAAA,IACjE,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,EACT,EAAE;AAEF,QAAM,oBAAgB,0BAAY,OAAO,UAAkB;AACzD,UAAM,KAAK,QAAQ;AACnB,iBAAa;AAAA,MACX,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,OAAO;AAAA,IACT,CAAC;AACD,WAAO,KAAK,SAAS;AAAA,EACvB,GAAG,CAAC,MAAM,QAAQ,SAAS,CAAC;AAE9B,8BAAU,MAAM;AACZ,UAAM,kBAAc,gCAAmB,MAAM,OAAO,SAAsB;AACxE,UAAI,MAAM;AACR,qBAAa;AAAA,UACX,UAAU;AAAA,UACV,QAAQ,KAAK;AAAA,UACb,SAAS;AAAA,UACT,OAAO,KAAK,WAAW;AAAA,UACvB,OAAO;AAAA,QACT,CAAC;AAAA,MACH,OAAO;AACL,qBAAa;AAAA,UACX,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,OAAO;AAAA,UACP,OAAO,IAAI,MAAM,2BAA2B;AAAA,QAC9C,CAAC;AACD,eAAO,KAAK,SAAS;AAAA,MACvB;AAAA,IACF,GAAG,CAAC,UAAU;AACZ,oBAAc,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,+BAA+B,CAAC;AAAA,IAC3F,CAAC;AAED,WAAO,MAAM,YAAY;AAAA,EAC3B,GAAG,CAAC,MAAM,eAAe,QAAQ,SAAS,CAAC;AAE3C,QAAM,mBAAmC,sBAAQ,OAAO;AAAA,IACtD,GAAG;AAAA,IACH,SAAS;AAAA,EACX,IAAI,CAAC,WAAW,MAAM,aAAa,CAAC;AAEpC,MAAI,CAAC,UAAU,UAAU;AACvB,WACE,4CAAC,mCAAc,UAAd,EAAuB,OAAO,cAC5B,8BACC,4CAAC,SAAI,aAAU,UAAS,aAAU,QAChC,sDAAC,UAAK,WAAU,WAAU,6CAA+B,GAC3D,GAEJ;AAAA,EAEJ;AAEA,SACI,4CAAC,mCAAc,UAAd,EAAuB,OAAO,cAC7B,UACF;AAEN;","names":[]}
@@ -0,0 +1,65 @@
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 background_exports = {};
20
+ __export(background_exports, {
21
+ AuthBackground: () => AuthBackground
22
+ });
23
+ module.exports = __toCommonJS(background_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ function AuthBackground() {
26
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
27
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
28
+ "div",
29
+ {
30
+ className: "absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80",
31
+ "aria-hidden": "true",
32
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
33
+ "div",
34
+ {
35
+ className: "relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]",
36
+ style: {
37
+ clipPath: "polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"
38
+ }
39
+ }
40
+ )
41
+ }
42
+ ),
43
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
44
+ "div",
45
+ {
46
+ className: "absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]",
47
+ "aria-hidden": "true",
48
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
49
+ "div",
50
+ {
51
+ className: "relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[hsl(var(--secondary)_/_0.3)] to-[hsl(var(--primary)_/_0.3)] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]",
52
+ style: {
53
+ clipPath: "polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"
54
+ }
55
+ }
56
+ )
57
+ }
58
+ )
59
+ ] });
60
+ }
61
+ // Annotate the CommonJS export names for ESM import in node:
62
+ 0 && (module.exports = {
63
+ AuthBackground
64
+ });
65
+ //# sourceMappingURL=background.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/background.tsx"],"sourcesContent":["export function AuthBackground() {\r\n return (\r\n <>\r\n {/* Primary gradient blob */}\r\n <div\r\n className=\"absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80\"\r\n aria-hidden=\"true\"\r\n >\r\n <div\r\n className=\"relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]\"\r\n style={{\r\n clipPath:\r\n 'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',\r\n }}\r\n />\r\n </div>\r\n \r\n {/* Secondary gradient blob */}\r\n <div\r\n className=\"absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]\"\r\n aria-hidden=\"true\"\r\n >\r\n <div\r\n className=\"relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[hsl(var(--secondary)_/_0.3)] to-[hsl(var(--primary)_/_0.3)] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]\"\r\n style={{\r\n clipPath:\r\n 'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',\r\n }}\r\n />\r\n </div>\r\n </>\r\n )\r\n }\r\n \r\n "],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEM;AAFC,SAAS,iBAAiB;AAC7B,SACE,4EAEE;AAAA;AAAA,MAAC;AAAA;AAAA,QACG,WAAU;AAAA,QACV,eAAY;AAAA,QAEZ;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,UACE;AAAA,YACJ;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,IAGF;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAY;AAAA,QAEZ;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,UACE;AAAA,YACJ;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
@@ -23,28 +23,86 @@ __export(sign_in_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(sign_in_exports);
25
25
  var import_jsx_runtime = require("react/jsx-runtime");
26
- var import_react2 = require("react");
27
- var import_actions = require("../app-router/client/actions");
28
- var import_create_styles = require("../utils/create-styles");
26
+ var import_react = require("react");
29
27
  var import_navigation = require("next/navigation");
28
+ var import_actions = require("../app-router/client/actions");
29
+ var import_card = require("./ui/card");
30
+ var import_input = require("./ui/input");
31
+ var import_label = require("./ui/label");
32
+ var import_button = require("./ui/button");
33
+ var import_alert = require("./ui/alert");
34
+ var import_separator = require("./ui/separator");
35
+ var import_utils = require("../lib/utils");
36
+ var import_lucide_react = require("lucide-react");
37
+ var import_auth = require("firebase/auth");
38
+ var import_client_init = require("../utils/client-init");
39
+ var import_sessionTernSecure = require("../app-router/server/sessionTernSecure");
40
+ var import_background = require("./background");
41
+ var import_construct = require("../utils/construct");
42
+ const isLocalhost = typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1");
43
+ const authDomain = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN;
44
+ const appName = process.env.NEXT_PUBLIC_FIREBASE_APP_NAME || "TernSecure";
30
45
  function SignIn({
46
+ redirectUrl,
31
47
  onError,
48
+ onSuccess,
32
49
  className,
33
- style,
34
50
  customStyles = {}
35
51
  }) {
36
- const [loading, setLoading] = (0, import_react2.useState)(false);
37
- const [error, setError] = (0, import_react2.useState)("");
38
- const [email, setEmail] = (0, import_react2.useState)("");
39
- const [password, setPassword] = (0, import_react2.useState)("");
40
- const router = (0, import_navigation.useRouter)();
52
+ const [loading, setLoading] = (0, import_react.useState)(false);
53
+ const [checkingRedirect, setCheckingRedirect] = (0, import_react.useState)(true);
54
+ const [error, setError] = (0, import_react.useState)("");
55
+ const [email, setEmail] = (0, import_react.useState)("");
56
+ const [password, setPassword] = (0, import_react.useState)("");
57
+ const searchParams = (0, import_navigation.useSearchParams)();
58
+ const isRedirectSignIn = searchParams.get("signInRedirect") === "true";
59
+ const handleRedirectResult = (0, import_react.useCallback)(async () => {
60
+ if (!isRedirectSignIn) return false;
61
+ setCheckingRedirect(true);
62
+ try {
63
+ console.log("Checking redirect result...");
64
+ console.log("Current hostname:", window.location.hostname);
65
+ console.log("Auth domain hostname:", authDomain);
66
+ const isOnAuth = authDomain && window.location.hostname === authDomain.replace(/https?:\/\//, "");
67
+ console.log("Is on AuthDomain:", isOnAuth);
68
+ const result = await (0, import_auth.getRedirectResult)(import_client_init.ternSecureAuth);
69
+ console.log("Redirect result:", result);
70
+ if (result) {
71
+ const idToken = await result.user.getIdToken();
72
+ const sessionResult = await (0, import_sessionTernSecure.createSessionCookie)(idToken);
73
+ if (!sessionResult.success) {
74
+ throw new Error("Failed to create session");
75
+ }
76
+ const storedRedirectUrl = sessionStorage.getItem("auth_return_url");
77
+ sessionStorage.removeItem("auth_redirect_url");
78
+ onSuccess == null ? void 0 : onSuccess();
79
+ window.location.href = storedRedirectUrl || (0, import_construct.getValidRedirectUrl)(redirectUrl, searchParams);
80
+ return true;
81
+ }
82
+ setCheckingRedirect(false);
83
+ } catch (err) {
84
+ console.error("Redirect result error:", err);
85
+ const errorMessage = err instanceof Error ? err.message : "Authentication failed";
86
+ setError(errorMessage);
87
+ onError == null ? void 0 : onError(err instanceof Error ? err : new Error(errorMessage));
88
+ sessionStorage.removeItem("auth_redirect_url");
89
+ return false;
90
+ }
91
+ }, [isRedirectSignIn, redirectUrl, searchParams, onSuccess, onError]);
92
+ (0, import_react.useEffect)(() => {
93
+ if (isRedirectSignIn) {
94
+ handleRedirectResult();
95
+ }
96
+ ;
97
+ }, [handleRedirectResult, isRedirectSignIn]);
41
98
  const handleSubmit = async (e) => {
42
99
  e.preventDefault();
43
100
  setLoading(true);
44
101
  try {
45
102
  const user = await (0, import_actions.signInWithEmail)(email, password);
46
103
  if (user.success) {
47
- router.push("/");
104
+ onSuccess == null ? void 0 : onSuccess();
105
+ window.location.href = (0, import_construct.getValidRedirectUrl)(redirectUrl, searchParams);
48
106
  }
49
107
  } catch (err) {
50
108
  const errorMessage = err instanceof Error ? err.message : "Failed to sign in";
@@ -54,76 +112,128 @@ function SignIn({
54
112
  setLoading(false);
55
113
  }
56
114
  };
57
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `${import_create_styles.styles.container} ${customStyles.container || ""}`, style, children: [
58
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `${import_create_styles.styles.header} ${customStyles.header || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: `${import_create_styles.styles.title} ${customStyles.title || ""}`, children: "Sign in to your account" }) }),
59
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `${import_create_styles.styles.formWrapper} ${customStyles.formWrapper || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `${import_create_styles.styles.formContainer} ${customStyles.formContainer || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
60
- "form",
61
- {
62
- onSubmit: handleSubmit,
63
- className: `${import_create_styles.styles.form} ${customStyles.form || ""} ${className}`,
64
- role: "form",
65
- "aria-label": "Sign in form",
66
- children: [
67
- error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
- "div",
69
- {
70
- className: `${import_create_styles.styles.error} ${customStyles.errorText || ""}`,
71
- role: "alert",
72
- "aria-live": "polite",
73
- children: error
74
- }
75
- ),
76
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
77
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "email", className: `${import_create_styles.styles.label} ${customStyles.label || ""}`, children: "Email" }),
115
+ const handleSocialSignIn = async (provider) => {
116
+ setLoading(true);
117
+ try {
118
+ const validRedirectUrl = (0, import_construct.getValidRedirectUrl)(redirectUrl, searchParams);
119
+ sessionStorage.setItem("auth_redirect_url", validRedirectUrl);
120
+ const currentUrl = new URL(window.location.href);
121
+ currentUrl.searchParams.set("signInRedirect", "true");
122
+ window.history.replaceState({}, "", currentUrl.toString());
123
+ const result = provider === "google" ? await (0, import_actions.signInWithRedirectGoogle)() : await (0, import_actions.signInWithMicrosoft)();
124
+ if (!result.success) {
125
+ throw new Error(result.error);
126
+ }
127
+ } catch (err) {
128
+ const errorMessage = err instanceof Error ? err.message : `Failed to sign in with ${provider}`;
129
+ setError(errorMessage);
130
+ onError == null ? void 0 : onError(err instanceof Error ? err : new Error(`Failed to sign in with ${provider}`));
131
+ setLoading(false);
132
+ sessionStorage.removeItem("auth_redirect_url");
133
+ }
134
+ };
135
+ if (checkingRedirect && isRedirectSignIn) {
136
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex min-h-screen items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-center space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto" }) }) });
137
+ }
138
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative flex items-center justify-center", children: [
139
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_background.AuthBackground, {}),
140
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_card.Card, { className: (0, import_utils.cn)("w-full max-w-md mx-auto mt-8", className, customStyles.card), children: [
141
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_card.CardHeader, { className: "space-y-1 text-center", children: [
142
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_card.CardTitle, { className: (0, import_utils.cn)("font-bold", customStyles.title), children: [
143
+ "Sign in to ",
144
+ `${appName}`
145
+ ] }),
146
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_card.CardDescription, { className: (0, import_utils.cn)("text-muted-foreground", customStyles.description), children: "Please sign in to continue" })
147
+ ] }),
148
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_card.CardContent, { className: "space-y-4", children: [
149
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
150
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_alert.Alert, { variant: "destructive", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_alert.AlertDescription, { children: error }) }),
151
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
152
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "email", className: (0, import_utils.cn)(customStyles.label), children: "Email" }),
78
153
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
79
- "input",
154
+ import_input.Input,
80
155
  {
81
156
  id: "email",
82
- name: "email",
83
157
  type: "email",
84
- placeholder: "Enter your email",
85
- required: true,
158
+ placeholder: "m@example.com",
86
159
  value: email,
87
160
  onChange: (e) => setEmail(e.target.value),
88
- className: `${import_create_styles.styles.input} ${customStyles.input || ""}`,
89
161
  disabled: loading,
90
- "aria-required": "true",
91
- "aria-invalid": !!error
162
+ className: (0, import_utils.cn)(customStyles.input),
163
+ required: true
92
164
  }
93
165
  )
94
166
  ] }),
95
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
96
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "password", className: `${import_create_styles.styles.label} ${customStyles.label || ""}`, children: "Password" }),
167
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "password", className: (0, import_utils.cn)(customStyles.label), children: "Password" }),
97
169
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
98
- "input",
170
+ import_input.Input,
99
171
  {
100
172
  id: "password",
101
- name: "password",
102
173
  type: "password",
103
- placeholder: "Enter your password",
104
- required: true,
105
174
  value: password,
106
175
  onChange: (e) => setPassword(e.target.value),
107
- className: `${import_create_styles.styles.input} ${customStyles.input || ""}`,
108
176
  disabled: loading,
109
- "aria-required": "true",
110
- "aria-invalid": !!error
177
+ className: (0, import_utils.cn)(customStyles.input),
178
+ required: true
111
179
  }
112
180
  )
113
181
  ] }),
114
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
115
- "button",
182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "submit", disabled: loading, className: (0, import_utils.cn)("w-full", customStyles.button), children: loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
184
+ "Signing in..."
185
+ ] }) : "Sign in" })
186
+ ] }),
187
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_separator.Separator, { className: (0, import_utils.cn)(customStyles.separator) }),
189
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "bg-background px-2 text-muted-foreground text-sm", children: "Or continue with" }) })
190
+ ] }),
191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid grid-cols-2 gap-4", children: [
192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
193
+ import_button.Button,
194
+ {
195
+ variant: "outline",
196
+ disabled: loading,
197
+ onClick: () => handleSocialSignIn("google"),
198
+ className: (0, import_utils.cn)("flex items-center justify-center", customStyles.socialButton),
199
+ children: [
200
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "w-5 h-5 mr-2", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: [
201
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z", fill: "#4285F4" }),
202
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z", fill: "#34A853" }),
203
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }),
204
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z", fill: "#EA4335" })
205
+ ] }),
206
+ "Google"
207
+ ]
208
+ }
209
+ ),
210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
211
+ import_button.Button,
116
212
  {
117
- type: "submit",
213
+ variant: "outline",
118
214
  disabled: loading,
119
- className: `${import_create_styles.styles.button} ${customStyles.button || ""}`,
120
- "data-testid": "sign-in-submit",
121
- children: loading ? "Signing in..." : "Sign in"
215
+ onClick: () => handleSocialSignIn("microsoft"),
216
+ className: (0, import_utils.cn)("flex items-center justify-center", customStyles.socialButton),
217
+ children: [
218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "w-5 h-5 mr-2", viewBox: "0 0 23 23", xmlns: "http://www.w3.org/2000/svg", children: [
219
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "#f3f3f3", d: "M0 0h23v23H0z" }),
220
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "#f35325", d: "M1 1h10v10H1z" }),
221
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "#81bc06", d: "M12 1h10v10H12z" }),
222
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "#05a6f0", d: "M1 12h10v10H1z" }),
223
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "#ffba08", d: "M12 12h10v10H12z" })
224
+ ] }),
225
+ "Microsoft"
226
+ ]
122
227
  }
123
228
  )
124
- ]
125
- }
126
- ) }) })
229
+ ] })
230
+ ] }),
231
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_card.CardFooter, { className: "flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-sm text-muted-foreground", children: [
232
+ "Don't have an account?",
233
+ " ",
234
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "#", className: "text-primary hover:underline", children: "Sign up" })
235
+ ] }) })
236
+ ] })
127
237
  ] });
128
238
  }
129
239
  // Annotate the CommonJS export names for ESM import in node: