@payez/next-mvp 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (654) hide show
  1. package/README.md +782 -0
  2. package/dist/api/auth-handler.d.ts +67 -0
  3. package/dist/api/auth-handler.js +397 -0
  4. package/dist/api/index.d.ts +10 -0
  5. package/dist/api/index.js +19 -0
  6. package/dist/api-handlers/account/change-password.d.ts +9 -0
  7. package/dist/api-handlers/account/change-password.js +112 -0
  8. package/dist/api-handlers/account/masked-info.d.ts +2 -0
  9. package/dist/api-handlers/account/masked-info.js +41 -0
  10. package/dist/api-handlers/account/profile.d.ts +3 -0
  11. package/dist/api-handlers/account/profile.js +63 -0
  12. package/dist/api-handlers/account/recovery/initiate.d.ts +2 -0
  13. package/dist/api-handlers/account/recovery/initiate.js +26 -0
  14. package/dist/api-handlers/account/recovery/send-code.d.ts +2 -0
  15. package/dist/api-handlers/account/recovery/send-code.js +28 -0
  16. package/dist/api-handlers/account/recovery/verify-code.d.ts +2 -0
  17. package/dist/api-handlers/account/recovery/verify-code.js +28 -0
  18. package/dist/api-handlers/account/reset-password.d.ts +2 -0
  19. package/dist/api-handlers/account/reset-password.js +26 -0
  20. package/dist/api-handlers/account/send-code.d.ts +24 -0
  21. package/dist/api-handlers/account/send-code.js +60 -0
  22. package/dist/api-handlers/account/update-phone.d.ts +27 -0
  23. package/dist/api-handlers/account/update-phone.js +64 -0
  24. package/dist/api-handlers/account/validate-password.d.ts +17 -0
  25. package/dist/api-handlers/account/validate-password.js +81 -0
  26. package/dist/api-handlers/account/verify-email.d.ts +26 -0
  27. package/dist/api-handlers/account/verify-email.js +106 -0
  28. package/dist/api-handlers/account/verify-sms.d.ts +26 -0
  29. package/dist/api-handlers/account/verify-sms.js +106 -0
  30. package/dist/api-handlers/admin/analytics.d.ts +20 -0
  31. package/dist/api-handlers/admin/analytics.js +379 -0
  32. package/dist/api-handlers/admin/audit.d.ts +20 -0
  33. package/dist/api-handlers/admin/audit.js +214 -0
  34. package/dist/api-handlers/admin/index.d.ts +21 -0
  35. package/dist/api-handlers/admin/index.js +41 -0
  36. package/dist/api-handlers/admin/redis-sessions.d.ts +36 -0
  37. package/dist/api-handlers/admin/redis-sessions.js +204 -0
  38. package/dist/api-handlers/admin/sessions.d.ts +21 -0
  39. package/dist/api-handlers/admin/sessions.js +284 -0
  40. package/dist/api-handlers/admin/site-logs.d.ts +46 -0
  41. package/dist/api-handlers/admin/site-logs.js +318 -0
  42. package/dist/api-handlers/admin/users.d.ts +20 -0
  43. package/dist/api-handlers/admin/users.js +222 -0
  44. package/dist/api-handlers/admin/vibe-data.d.ts +80 -0
  45. package/dist/api-handlers/admin/vibe-data.js +268 -0
  46. package/dist/api-handlers/anon/preferences.d.ts +37 -0
  47. package/dist/api-handlers/anon/preferences.js +96 -0
  48. package/dist/api-handlers/auth/jwks.d.ts +2 -0
  49. package/dist/api-handlers/auth/jwks.js +24 -0
  50. package/dist/api-handlers/auth/login.d.ts +42 -0
  51. package/dist/api-handlers/auth/login.js +178 -0
  52. package/dist/api-handlers/auth/refresh.d.ts +74 -0
  53. package/dist/api-handlers/auth/refresh.js +635 -0
  54. package/dist/api-handlers/auth/signout.d.ts +37 -0
  55. package/dist/api-handlers/auth/signout.js +187 -0
  56. package/dist/api-handlers/auth/status.d.ts +8 -0
  57. package/dist/api-handlers/auth/status.js +26 -0
  58. package/dist/api-handlers/auth/update-session.d.ts +37 -0
  59. package/dist/api-handlers/auth/update-session.js +95 -0
  60. package/dist/api-handlers/auth/validate.d.ts +6 -0
  61. package/dist/api-handlers/auth/validate.js +43 -0
  62. package/dist/api-handlers/auth/verify-code.d.ts +43 -0
  63. package/dist/api-handlers/auth/verify-code.js +94 -0
  64. package/dist/api-handlers/session/refresh-viability.d.ts +14 -0
  65. package/dist/api-handlers/session/refresh-viability.js +39 -0
  66. package/dist/api-handlers/session/viability.d.ts +13 -0
  67. package/dist/api-handlers/session/viability.js +146 -0
  68. package/dist/api-handlers/test/force-expire.d.ts +23 -0
  69. package/dist/api-handlers/test/force-expire.js +65 -0
  70. package/dist/auth/auth-decision.d.ts +39 -0
  71. package/dist/auth/auth-decision.js +182 -0
  72. package/dist/auth/auth-options.d.ts +57 -0
  73. package/dist/auth/auth-options.js +213 -0
  74. package/dist/auth/callbacks/index.d.ts +6 -0
  75. package/dist/auth/callbacks/index.js +12 -0
  76. package/dist/auth/callbacks/jwt.d.ts +45 -0
  77. package/dist/auth/callbacks/jwt.js +305 -0
  78. package/dist/auth/callbacks/session.d.ts +60 -0
  79. package/dist/auth/callbacks/session.js +170 -0
  80. package/dist/auth/callbacks/signin.d.ts +23 -0
  81. package/dist/auth/callbacks/signin.js +44 -0
  82. package/dist/auth/events/index.d.ts +4 -0
  83. package/dist/auth/events/index.js +8 -0
  84. package/dist/auth/events/signout.d.ts +17 -0
  85. package/dist/auth/events/signout.js +32 -0
  86. package/dist/auth/providers/credentials.d.ts +32 -0
  87. package/dist/auth/providers/credentials.js +223 -0
  88. package/dist/auth/providers/index.d.ts +5 -0
  89. package/dist/auth/providers/index.js +21 -0
  90. package/dist/auth/providers/oauth.d.ts +26 -0
  91. package/dist/auth/providers/oauth.js +105 -0
  92. package/dist/auth/route-config.d.ts +66 -0
  93. package/dist/auth/route-config.js +190 -0
  94. package/dist/auth/types/auth-types.d.ts +417 -0
  95. package/dist/auth/types/auth-types.js +53 -0
  96. package/dist/auth/types/index.d.ts +6 -0
  97. package/dist/auth/types/index.js +22 -0
  98. package/dist/auth/unauthenticated-routes.d.ts +1 -0
  99. package/dist/auth/unauthenticated-routes.js +19 -0
  100. package/dist/auth/utils/idp-client.d.ts +94 -0
  101. package/dist/auth/utils/idp-client.js +383 -0
  102. package/dist/auth/utils/index.d.ts +5 -0
  103. package/dist/auth/utils/index.js +21 -0
  104. package/dist/auth/utils/token-utils.d.ts +84 -0
  105. package/dist/auth/utils/token-utils.js +219 -0
  106. package/dist/client/AuthContext.d.ts +19 -0
  107. package/dist/client/AuthContext.js +112 -0
  108. package/dist/client/fetch-with-auth.d.ts +11 -0
  109. package/dist/client/fetch-with-auth.js +44 -0
  110. package/dist/client/fetchWithSession.d.ts +3 -0
  111. package/dist/client/fetchWithSession.js +24 -0
  112. package/dist/client/index.d.ts +9 -0
  113. package/dist/client/index.js +20 -0
  114. package/dist/client/useAnonSession.d.ts +36 -0
  115. package/dist/client/useAnonSession.js +99 -0
  116. package/dist/components/SessionSync.d.ts +13 -0
  117. package/dist/components/SessionSync.js +119 -0
  118. package/dist/components/SignalRHealthCheck.d.ts +10 -0
  119. package/dist/components/SignalRHealthCheck.js +97 -0
  120. package/dist/components/account/UserAvatarMenu.d.ts +20 -0
  121. package/dist/components/account/UserAvatarMenu.js +80 -0
  122. package/dist/components/account/index.d.ts +7 -0
  123. package/dist/components/account/index.js +10 -0
  124. package/dist/components/admin/AlertSettingsTab.d.ts +48 -0
  125. package/dist/components/admin/AlertSettingsTab.js +351 -0
  126. package/dist/components/admin/AnalyticsTab.d.ts +22 -0
  127. package/dist/components/admin/AnalyticsTab.js +167 -0
  128. package/dist/components/admin/DataBrowserTab.d.ts +19 -0
  129. package/dist/components/admin/DataBrowserTab.js +252 -0
  130. package/dist/components/admin/LoggingSettingsTab.d.ts +73 -0
  131. package/dist/components/admin/LoggingSettingsTab.js +339 -0
  132. package/dist/components/admin/SessionsTab.d.ts +37 -0
  133. package/dist/components/admin/SessionsTab.js +165 -0
  134. package/dist/components/admin/StatsTab.d.ts +53 -0
  135. package/dist/components/admin/StatsTab.js +161 -0
  136. package/dist/components/admin/VibeAdminContext.d.ts +32 -0
  137. package/dist/components/admin/VibeAdminContext.js +38 -0
  138. package/dist/components/admin/VibeAdminLayout.d.ts +11 -0
  139. package/dist/components/admin/VibeAdminLayout.js +69 -0
  140. package/dist/components/admin/index.d.ts +29 -0
  141. package/dist/components/admin/index.js +44 -0
  142. package/dist/components/auth/FederatedAuthSection.d.ts +8 -0
  143. package/dist/components/auth/FederatedAuthSection.js +45 -0
  144. package/dist/components/auth/ModeAwareLoginPage.d.ts +10 -0
  145. package/dist/components/auth/ModeAwareLoginPage.js +42 -0
  146. package/dist/components/auth/ModeAwareSignupPage.d.ts +9 -0
  147. package/dist/components/auth/ModeAwareSignupPage.js +78 -0
  148. package/dist/components/auth/TraditionalAuthSection.d.ts +14 -0
  149. package/dist/components/auth/TraditionalAuthSection.js +20 -0
  150. package/dist/components/recovery/CompleteStep.d.ts +5 -0
  151. package/dist/components/recovery/CompleteStep.js +8 -0
  152. package/dist/components/recovery/InitiateRecoveryStep.d.ts +8 -0
  153. package/dist/components/recovery/InitiateRecoveryStep.js +20 -0
  154. package/dist/components/recovery/SelectMethodStep.d.ts +8 -0
  155. package/dist/components/recovery/SelectMethodStep.js +8 -0
  156. package/dist/components/recovery/SetPasswordStep.d.ts +6 -0
  157. package/dist/components/recovery/SetPasswordStep.js +20 -0
  158. package/dist/components/recovery/VerifyCodeStep.d.ts +10 -0
  159. package/dist/components/recovery/VerifyCodeStep.js +24 -0
  160. package/dist/components/reserved/ReservedRecoveryWarning.d.ts +38 -0
  161. package/dist/components/reserved/ReservedRecoveryWarning.js +92 -0
  162. package/dist/components/reserved/ReservedStatusBox.d.ts +30 -0
  163. package/dist/components/reserved/ReservedStatusBox.js +71 -0
  164. package/dist/components/ui/BetaBadge.d.ts +29 -0
  165. package/dist/components/ui/BetaBadge.js +38 -0
  166. package/dist/components/ui/Footer.d.ts +37 -0
  167. package/dist/components/ui/Footer.js +41 -0
  168. package/dist/config/env.d.ts +66 -0
  169. package/dist/config/env.js +57 -0
  170. package/dist/config/logger.d.ts +57 -0
  171. package/dist/config/logger.js +73 -0
  172. package/dist/config/logging-config.d.ts +30 -0
  173. package/dist/config/logging-config.js +122 -0
  174. package/dist/config/unauthenticated-routes.d.ts +17 -0
  175. package/dist/config/unauthenticated-routes.js +24 -0
  176. package/dist/config/vibe-log-transport.d.ts +79 -0
  177. package/dist/config/vibe-log-transport.js +203 -0
  178. package/dist/edge/internal-api-url.d.ts +53 -0
  179. package/dist/edge/internal-api-url.js +63 -0
  180. package/dist/edge/middleware.d.ts +14 -0
  181. package/dist/edge/middleware.js +32 -0
  182. package/dist/hooks/useAuth.d.ts +23 -0
  183. package/dist/hooks/useAuth.js +81 -0
  184. package/dist/hooks/useAuthSettings.d.ts +59 -0
  185. package/dist/hooks/useAuthSettings.js +93 -0
  186. package/dist/hooks/useAvailableProviders.d.ts +45 -0
  187. package/dist/hooks/useAvailableProviders.js +108 -0
  188. package/dist/hooks/usePasswordValidation.d.ts +27 -0
  189. package/dist/hooks/usePasswordValidation.js +102 -0
  190. package/dist/hooks/useProfile.d.ts +15 -0
  191. package/dist/hooks/useProfile.js +59 -0
  192. package/dist/hooks/usePublicAuthSettings.d.ts +56 -0
  193. package/dist/hooks/usePublicAuthSettings.js +131 -0
  194. package/dist/hooks/useSessionExpiration.d.ts +57 -0
  195. package/dist/hooks/useSessionExpiration.js +72 -0
  196. package/dist/hooks/useViabilitySession.d.ts +75 -0
  197. package/dist/hooks/useViabilitySession.js +268 -0
  198. package/dist/index.d.ts +12 -0
  199. package/dist/index.js +54 -0
  200. package/dist/lib/anon-session.d.ts +74 -0
  201. package/dist/lib/anon-session.js +169 -0
  202. package/dist/lib/api-handler.d.ts +123 -0
  203. package/dist/lib/api-handler.js +478 -0
  204. package/dist/lib/app-slug.d.ts +95 -0
  205. package/dist/lib/app-slug.js +172 -0
  206. package/dist/lib/demo-mode.d.ts +6 -0
  207. package/dist/lib/demo-mode.js +16 -0
  208. package/dist/lib/geolocation.d.ts +64 -0
  209. package/dist/lib/geolocation.js +235 -0
  210. package/dist/lib/idp-client-config.d.ts +75 -0
  211. package/dist/lib/idp-client-config.js +351 -0
  212. package/dist/lib/idp-fetch.d.ts +14 -0
  213. package/dist/lib/idp-fetch.js +91 -0
  214. package/dist/lib/internal-api.d.ts +87 -0
  215. package/dist/lib/internal-api.js +122 -0
  216. package/dist/lib/jwt-decode-client.d.ts +10 -0
  217. package/dist/lib/jwt-decode-client.js +46 -0
  218. package/dist/lib/jwt-decode.d.ts +48 -0
  219. package/dist/lib/jwt-decode.js +57 -0
  220. package/dist/lib/nextauth-secret.d.ts +10 -0
  221. package/dist/lib/nextauth-secret.js +104 -0
  222. package/dist/lib/rate-limit-service.d.ts +23 -0
  223. package/dist/lib/rate-limit-service.js +6 -0
  224. package/dist/lib/redis.d.ts +5 -0
  225. package/dist/lib/redis.js +28 -0
  226. package/dist/lib/refresh-token-validator.d.ts +13 -0
  227. package/dist/lib/refresh-token-validator.js +117 -0
  228. package/dist/lib/roles.d.ts +145 -0
  229. package/dist/lib/roles.js +168 -0
  230. package/dist/lib/secret-validation.d.ts +4 -0
  231. package/dist/lib/secret-validation.js +14 -0
  232. package/dist/lib/session-store.d.ts +166 -0
  233. package/dist/lib/session-store.js +537 -0
  234. package/dist/lib/session.d.ts +21 -0
  235. package/dist/lib/session.js +26 -0
  236. package/dist/lib/site-logger.d.ts +214 -0
  237. package/dist/lib/site-logger.js +210 -0
  238. package/dist/lib/standardized-client-api.d.ts +161 -0
  239. package/dist/lib/standardized-client-api.js +786 -0
  240. package/dist/lib/startup-init.d.ts +40 -0
  241. package/dist/lib/startup-init.js +261 -0
  242. package/dist/lib/test-aware-get-token.d.ts +2 -0
  243. package/dist/lib/test-aware-get-token.js +81 -0
  244. package/dist/lib/token-expiry.d.ts +14 -0
  245. package/dist/lib/token-expiry.js +39 -0
  246. package/dist/lib/token-lifecycle.d.ts +52 -0
  247. package/dist/lib/token-lifecycle.js +398 -0
  248. package/dist/lib/types/api-responses.d.ts +128 -0
  249. package/dist/lib/types/api-responses.js +171 -0
  250. package/dist/lib/user-agent-parser.d.ts +50 -0
  251. package/dist/lib/user-agent-parser.js +220 -0
  252. package/dist/logging/api/admin-analytics.d.ts +3 -0
  253. package/dist/logging/api/admin-analytics.js +45 -0
  254. package/dist/logging/api/audit-log.d.ts +3 -0
  255. package/dist/logging/api/audit-log.js +52 -0
  256. package/dist/logging/components/AdminAnalyticsLayout.d.ts +10 -0
  257. package/dist/logging/components/AdminAnalyticsLayout.js +11 -0
  258. package/dist/logging/components/AuditLogViewer.d.ts +7 -0
  259. package/dist/logging/components/AuditLogViewer.js +51 -0
  260. package/dist/logging/components/ErrorMetricsCard.d.ts +7 -0
  261. package/dist/logging/components/ErrorMetricsCard.js +16 -0
  262. package/dist/logging/components/HealthMetricsCard.d.ts +7 -0
  263. package/dist/logging/components/HealthMetricsCard.js +19 -0
  264. package/dist/logging/hooks/useAdminAnalytics.d.ts +24 -0
  265. package/dist/logging/hooks/useAdminAnalytics.js +22 -0
  266. package/dist/logging/hooks/useAuditLog.d.ts +6 -0
  267. package/dist/logging/hooks/useAuditLog.js +25 -0
  268. package/dist/logging/hooks/useErrorMetrics.d.ts +6 -0
  269. package/dist/logging/hooks/useErrorMetrics.js +38 -0
  270. package/dist/logging/hooks/useHealthMetrics.d.ts +6 -0
  271. package/dist/logging/hooks/useHealthMetrics.js +41 -0
  272. package/dist/logging/index.d.ts +11 -0
  273. package/dist/logging/index.js +40 -0
  274. package/dist/logging/types/analytics.d.ts +68 -0
  275. package/dist/logging/types/analytics.js +3 -0
  276. package/dist/logging/types/audit.d.ts +29 -0
  277. package/dist/logging/types/audit.js +2 -0
  278. package/dist/logging/types/index.d.ts +2 -0
  279. package/dist/logging/types/index.js +19 -0
  280. package/dist/middleware/auth-decision.d.ts +33 -0
  281. package/dist/middleware/auth-decision.js +65 -0
  282. package/dist/middleware/create-middleware.d.ts +100 -0
  283. package/dist/middleware/create-middleware.js +445 -0
  284. package/dist/middleware/rbac-check.d.ts +44 -0
  285. package/dist/middleware/rbac-check.js +191 -0
  286. package/dist/middleware/twofa-presets.d.ts +134 -0
  287. package/dist/middleware/twofa-presets.js +175 -0
  288. package/dist/models/DecodedAccessToken.d.ts +17 -0
  289. package/dist/models/DecodedAccessToken.js +2 -0
  290. package/dist/models/SessionModel.d.ts +122 -0
  291. package/dist/models/SessionModel.js +136 -0
  292. package/dist/pages/admin-login/page.d.ts +31 -0
  293. package/dist/pages/admin-login/page.js +83 -0
  294. package/dist/pages/admin-roles/RolesAdminPage.d.ts +15 -0
  295. package/dist/pages/admin-roles/RolesAdminPage.js +78 -0
  296. package/dist/pages/admin-roles/index.d.ts +8 -0
  297. package/dist/pages/admin-roles/index.js +15 -0
  298. package/dist/pages/admin-roles/modals.d.ts +72 -0
  299. package/dist/pages/admin-roles/modals.js +154 -0
  300. package/dist/pages/client-admin/ClientSiteAdminPage.d.ts +79 -0
  301. package/dist/pages/client-admin/ClientSiteAdminPage.js +177 -0
  302. package/dist/pages/client-admin/index.d.ts +32 -0
  303. package/dist/pages/client-admin/index.js +37 -0
  304. package/dist/pages/login/page.d.ts +22 -0
  305. package/dist/pages/login/page.js +239 -0
  306. package/dist/pages/profile/EnhancedProfilePage.d.ts +13 -0
  307. package/dist/pages/profile/EnhancedProfilePage.js +150 -0
  308. package/dist/pages/profile/index.d.ts +8 -0
  309. package/dist/pages/profile/index.js +16 -0
  310. package/dist/pages/profile/page.d.ts +19 -0
  311. package/dist/pages/profile/page.js +47 -0
  312. package/dist/pages/profile/profile-patch.d.ts +1 -0
  313. package/dist/pages/profile/profile-patch.js +281 -0
  314. package/dist/pages/recovery/page.d.ts +1 -0
  315. package/dist/pages/recovery/page.js +142 -0
  316. package/dist/pages/roles/MyRolesPage.d.ts +24 -0
  317. package/dist/pages/roles/MyRolesPage.js +71 -0
  318. package/dist/pages/roles/components.d.ts +63 -0
  319. package/dist/pages/roles/components.js +108 -0
  320. package/dist/pages/roles/index.d.ts +8 -0
  321. package/dist/pages/roles/index.js +19 -0
  322. package/dist/pages/security/EnhancedSecurityPage.d.ts +14 -0
  323. package/dist/pages/security/EnhancedSecurityPage.js +248 -0
  324. package/dist/pages/security/index.d.ts +8 -0
  325. package/dist/pages/security/index.js +16 -0
  326. package/dist/pages/security/page.d.ts +21 -0
  327. package/dist/pages/security/page.js +212 -0
  328. package/dist/pages/security/security-patch.d.ts +1 -0
  329. package/dist/pages/security/security-patch.js +302 -0
  330. package/dist/pages/settings/EnhancedSettingsPage.d.ts +46 -0
  331. package/dist/pages/settings/EnhancedSettingsPage.js +231 -0
  332. package/dist/pages/settings/index.d.ts +8 -0
  333. package/dist/pages/settings/index.js +16 -0
  334. package/dist/pages/settings/page.d.ts +7 -0
  335. package/dist/pages/settings/page.js +26 -0
  336. package/dist/pages/showcase/ShowcasePage.d.ts +13 -0
  337. package/dist/pages/showcase/ShowcasePage.js +140 -0
  338. package/dist/pages/showcase/index.d.ts +12 -0
  339. package/dist/pages/showcase/index.js +17 -0
  340. package/dist/pages/test-env/EmergencyLogoutPage.d.ts +14 -0
  341. package/dist/pages/test-env/EmergencyLogoutPage.js +98 -0
  342. package/dist/pages/test-env/JwtInspectPage.d.ts +14 -0
  343. package/dist/pages/test-env/JwtInspectPage.js +114 -0
  344. package/dist/pages/test-env/RefreshTokenPage.d.ts +15 -0
  345. package/dist/pages/test-env/RefreshTokenPage.js +91 -0
  346. package/dist/pages/test-env/TestEnvPage.d.ts +13 -0
  347. package/dist/pages/test-env/TestEnvPage.js +49 -0
  348. package/dist/pages/test-env/index.d.ts +24 -0
  349. package/dist/pages/test-env/index.js +32 -0
  350. package/dist/pages/verify-code/page.d.ts +30 -0
  351. package/dist/pages/verify-code/page.js +408 -0
  352. package/dist/routes/account/index.d.ts +28 -0
  353. package/dist/routes/account/index.js +71 -0
  354. package/dist/routes/account/masked-info.d.ts +33 -0
  355. package/dist/routes/account/masked-info.js +39 -0
  356. package/dist/routes/account/send-code.d.ts +37 -0
  357. package/dist/routes/account/send-code.js +42 -0
  358. package/dist/routes/account/update-phone.d.ts +13 -0
  359. package/dist/routes/account/update-phone.js +17 -0
  360. package/dist/routes/account/verify-email.d.ts +38 -0
  361. package/dist/routes/account/verify-email.js +43 -0
  362. package/dist/routes/account/verify-sms.d.ts +38 -0
  363. package/dist/routes/account/verify-sms.js +43 -0
  364. package/dist/routes/auth/index.d.ts +19 -0
  365. package/dist/routes/auth/index.js +64 -0
  366. package/dist/routes/auth/logout.d.ts +31 -0
  367. package/dist/routes/auth/logout.js +113 -0
  368. package/dist/routes/auth/nextauth.d.ts +19 -0
  369. package/dist/routes/auth/nextauth.js +72 -0
  370. package/dist/routes/auth/refresh.d.ts +30 -0
  371. package/dist/routes/auth/refresh.js +51 -0
  372. package/dist/routes/auth/session.d.ts +72 -0
  373. package/dist/routes/auth/session.js +180 -0
  374. package/dist/routes/auth/settings.d.ts +25 -0
  375. package/dist/routes/auth/settings.js +55 -0
  376. package/dist/routes/auth/viability.d.ts +52 -0
  377. package/dist/routes/auth/viability.js +201 -0
  378. package/dist/routes/index.d.ts +12 -0
  379. package/dist/routes/index.js +54 -0
  380. package/dist/routes/session/index.d.ts +6 -0
  381. package/dist/routes/session/index.js +10 -0
  382. package/dist/routes/session/refresh-viability.d.ts +16 -0
  383. package/dist/routes/session/refresh-viability.js +20 -0
  384. package/dist/services/signalrActivityService.d.ts +44 -0
  385. package/dist/services/signalrActivityService.js +257 -0
  386. package/dist/stores/authStore.d.ts +154 -0
  387. package/dist/stores/authStore.js +1531 -0
  388. package/dist/theme/ThemeProvider.d.ts +14 -0
  389. package/dist/theme/ThemeProvider.js +28 -0
  390. package/dist/theme/default.d.ts +8 -0
  391. package/dist/theme/default.js +33 -0
  392. package/dist/theme/index.d.ts +15 -0
  393. package/dist/theme/index.js +25 -0
  394. package/dist/theme/types.d.ts +56 -0
  395. package/dist/theme/types.js +8 -0
  396. package/dist/theme/useTheme.d.ts +60 -0
  397. package/dist/theme/useTheme.js +63 -0
  398. package/dist/theme/utils.d.ts +13 -0
  399. package/dist/theme/utils.js +39 -0
  400. package/dist/types/api.d.ts +134 -0
  401. package/dist/types/api.js +44 -0
  402. package/dist/types/auth.d.ts +19 -0
  403. package/dist/types/auth.js +2 -0
  404. package/dist/types/logging.d.ts +42 -0
  405. package/dist/types/logging.js +2 -0
  406. package/dist/types/recovery.d.ts +48 -0
  407. package/dist/types/recovery.js +2 -0
  408. package/dist/types/security.d.ts +1 -0
  409. package/dist/types/security.js +2 -0
  410. package/dist/utils/api.d.ts +85 -0
  411. package/dist/utils/api.js +287 -0
  412. package/dist/utils/circuitBreaker.d.ts +43 -0
  413. package/dist/utils/circuitBreaker.js +91 -0
  414. package/dist/utils/error-message.d.ts +1 -0
  415. package/dist/utils/error-message.js +103 -0
  416. package/dist/utils/layout/reservedSpace.d.ts +59 -0
  417. package/dist/utils/layout/reservedSpace.js +102 -0
  418. package/dist/utils/logout.d.ts +14 -0
  419. package/dist/utils/logout.js +32 -0
  420. package/dist/vibe/client.d.ts +261 -0
  421. package/dist/vibe/client.js +445 -0
  422. package/dist/vibe/errors.d.ts +83 -0
  423. package/dist/vibe/errors.js +146 -0
  424. package/dist/vibe/generic.d.ts +234 -0
  425. package/dist/vibe/generic.js +369 -0
  426. package/dist/vibe/hooks/index.d.ts +169 -0
  427. package/dist/vibe/hooks/index.js +252 -0
  428. package/dist/vibe/index.d.ts +23 -0
  429. package/dist/vibe/index.js +67 -0
  430. package/dist/vibe/sessions.d.ts +161 -0
  431. package/dist/vibe/sessions.js +391 -0
  432. package/dist/vibe/types.d.ts +353 -0
  433. package/dist/vibe/types.js +315 -0
  434. package/package.json +855 -0
  435. package/scripts/check-internal-url-usage.sh +73 -0
  436. package/scripts/dev-broker.ps1 +35 -0
  437. package/scripts/dev-local.ps1 +45 -0
  438. package/src/api/auth-handler.ts +550 -0
  439. package/src/api/index.ts +18 -0
  440. package/src/api-handlers/account/change-password.ts +145 -0
  441. package/src/api-handlers/account/masked-info.ts +45 -0
  442. package/src/api-handlers/account/profile.ts +80 -0
  443. package/src/api-handlers/account/recovery/initiate.ts +23 -0
  444. package/src/api-handlers/account/recovery/send-code.ts +25 -0
  445. package/src/api-handlers/account/recovery/verify-code.ts +25 -0
  446. package/src/api-handlers/account/reset-password.ts +23 -0
  447. package/src/api-handlers/account/send-code.ts +76 -0
  448. package/src/api-handlers/account/update-phone.ts +79 -0
  449. package/src/api-handlers/account/validate-password.ts +118 -0
  450. package/src/api-handlers/account/verify-email.ts +125 -0
  451. package/src/api-handlers/account/verify-sms.ts +125 -0
  452. package/src/api-handlers/admin/analytics.ts +445 -0
  453. package/src/api-handlers/admin/audit.ts +225 -0
  454. package/src/api-handlers/admin/index.ts +59 -0
  455. package/src/api-handlers/admin/redis-sessions.ts +253 -0
  456. package/src/api-handlers/admin/sessions.ts +320 -0
  457. package/src/api-handlers/admin/site-logs.ts +367 -0
  458. package/src/api-handlers/admin/users.ts +244 -0
  459. package/src/api-handlers/admin/vibe-data.ts +326 -0
  460. package/src/api-handlers/anon/preferences.ts +123 -0
  461. package/src/api-handlers/auth/jwks.ts +20 -0
  462. package/src/api-handlers/auth/login.ts +240 -0
  463. package/src/api-handlers/auth/refresh.ts +687 -0
  464. package/src/api-handlers/auth/signout.ts +212 -0
  465. package/src/api-handlers/auth/status.ts +23 -0
  466. package/src/api-handlers/auth/update-session.ts +125 -0
  467. package/src/api-handlers/auth/validate.ts +44 -0
  468. package/src/api-handlers/auth/verify-code.ts +129 -0
  469. package/src/api-handlers/session/refresh-viability.ts +36 -0
  470. package/src/api-handlers/session/viability.ts +166 -0
  471. package/src/api-handlers/test/force-expire.ts +67 -0
  472. package/src/auth/auth-decision.ts +230 -0
  473. package/src/auth/auth-options.ts +237 -0
  474. package/src/auth/callbacks/index.ts +7 -0
  475. package/src/auth/callbacks/jwt.ts +382 -0
  476. package/src/auth/callbacks/session.ts +243 -0
  477. package/src/auth/callbacks/signin.ts +56 -0
  478. package/src/auth/events/index.ts +5 -0
  479. package/src/auth/events/signout.ts +33 -0
  480. package/src/auth/providers/credentials.ts +256 -0
  481. package/src/auth/providers/index.ts +6 -0
  482. package/src/auth/providers/oauth.ts +114 -0
  483. package/src/auth/route-config.ts +220 -0
  484. package/src/auth/types/auth-types.ts +555 -0
  485. package/src/auth/types/index.ts +7 -0
  486. package/src/auth/unauthenticated-routes.ts +3 -0
  487. package/src/auth/utils/idp-client.ts +444 -0
  488. package/src/auth/utils/index.ts +6 -0
  489. package/src/auth/utils/token-utils.ts +244 -0
  490. package/src/client/AuthContext.tsx +140 -0
  491. package/src/client/fetch-with-auth.ts +48 -0
  492. package/src/client/fetchWithSession.ts +21 -0
  493. package/src/client/index.ts +13 -0
  494. package/src/client/useAnonSession.ts +131 -0
  495. package/src/components/SessionSync.tsx +137 -0
  496. package/src/components/SignalRHealthCheck.tsx +131 -0
  497. package/src/components/account/UserAvatarMenu.tsx +217 -0
  498. package/src/components/account/index.ts +8 -0
  499. package/src/components/admin/AlertSettingsTab.tsx +728 -0
  500. package/src/components/admin/AnalyticsTab.tsx +703 -0
  501. package/src/components/admin/DataBrowserTab.tsx +505 -0
  502. package/src/components/admin/LoggingSettingsTab.tsx +665 -0
  503. package/src/components/admin/SessionsTab.tsx +414 -0
  504. package/src/components/admin/StatsTab.tsx +379 -0
  505. package/src/components/admin/VibeAdminContext.tsx +87 -0
  506. package/src/components/admin/VibeAdminLayout.tsx +185 -0
  507. package/src/components/admin/index.ts +59 -0
  508. package/src/components/auth/FederatedAuthSection.tsx +95 -0
  509. package/src/components/auth/ModeAwareLoginPage.tsx +135 -0
  510. package/src/components/auth/ModeAwareSignupPage.tsx +267 -0
  511. package/src/components/auth/TraditionalAuthSection.tsx +99 -0
  512. package/src/components/recovery/CompleteStep.tsx +36 -0
  513. package/src/components/recovery/InitiateRecoveryStep.tsx +68 -0
  514. package/src/components/recovery/SelectMethodStep.tsx +73 -0
  515. package/src/components/recovery/SetPasswordStep.tsx +97 -0
  516. package/src/components/recovery/VerifyCodeStep.tsx +90 -0
  517. package/src/components/reserved/ReservedRecoveryWarning.tsx +160 -0
  518. package/src/components/reserved/ReservedStatusBox.tsx +118 -0
  519. package/src/components/ui/BetaBadge.tsx +58 -0
  520. package/src/components/ui/Footer.tsx +93 -0
  521. package/src/config/env.ts +57 -0
  522. package/src/config/logger.ts +62 -0
  523. package/src/config/logging-config.ts +82 -0
  524. package/src/config/unauthenticated-routes.ts +19 -0
  525. package/src/config/vibe-log-transport.ts +250 -0
  526. package/src/edge/internal-api-url.ts +65 -0
  527. package/src/edge/middleware.ts +42 -0
  528. package/src/hooks/useAuth.ts +115 -0
  529. package/src/hooks/useAuthSettings.ts +97 -0
  530. package/src/hooks/useAvailableProviders.ts +118 -0
  531. package/src/hooks/usePasswordValidation.ts +127 -0
  532. package/src/hooks/useProfile.ts +75 -0
  533. package/src/hooks/usePublicAuthSettings.ts +149 -0
  534. package/src/hooks/useSessionExpiration.ts +102 -0
  535. package/src/hooks/useViabilitySession.ts +335 -0
  536. package/src/index.ts +63 -0
  537. package/src/lib/anon-session.ts +213 -0
  538. package/src/lib/api-handler.ts +625 -0
  539. package/src/lib/app-slug.ts +178 -0
  540. package/src/lib/demo-mode.ts +13 -0
  541. package/src/lib/geolocation.ts +265 -0
  542. package/src/lib/idp-client-config.ts +442 -0
  543. package/src/lib/idp-fetch.ts +101 -0
  544. package/src/lib/internal-api.ts +171 -0
  545. package/src/lib/jwt-decode-client.ts +45 -0
  546. package/src/lib/jwt-decode.ts +83 -0
  547. package/src/lib/nextauth-secret.ts +126 -0
  548. package/src/lib/rate-limit-service.ts +9 -0
  549. package/src/lib/redis.ts +27 -0
  550. package/src/lib/refresh-token-validator.ts +64 -0
  551. package/src/lib/roles.ts +177 -0
  552. package/src/lib/secret-validation.ts +8 -0
  553. package/src/lib/session-store.ts +637 -0
  554. package/src/lib/session.ts +34 -0
  555. package/src/lib/site-logger.ts +245 -0
  556. package/src/lib/standardized-client-api.ts +896 -0
  557. package/src/lib/startup-init.ts +247 -0
  558. package/src/lib/test-aware-get-token.ts +30 -0
  559. package/src/lib/token-expiry.ts +40 -0
  560. package/src/lib/token-lifecycle.ts +477 -0
  561. package/src/lib/types/api-responses.ts +336 -0
  562. package/src/lib/user-agent-parser.ts +252 -0
  563. package/src/logging/api/admin-analytics.ts +51 -0
  564. package/src/logging/api/audit-log.ts +53 -0
  565. package/src/logging/components/AdminAnalyticsLayout.tsx +49 -0
  566. package/src/logging/components/AuditLogViewer.tsx +125 -0
  567. package/src/logging/components/ErrorMetricsCard.tsx +98 -0
  568. package/src/logging/components/HealthMetricsCard.tsx +70 -0
  569. package/src/logging/hooks/useAdminAnalytics.ts +22 -0
  570. package/src/logging/hooks/useAuditLog.ts +24 -0
  571. package/src/logging/hooks/useErrorMetrics.ts +40 -0
  572. package/src/logging/hooks/useHealthMetrics.ts +44 -0
  573. package/src/logging/index.ts +18 -0
  574. package/src/logging/types/analytics.ts +81 -0
  575. package/src/logging/types/audit.ts +31 -0
  576. package/src/logging/types/index.ts +3 -0
  577. package/src/middleware/auth-decision.ts +43 -0
  578. package/src/middleware/create-middleware.ts +626 -0
  579. package/src/middleware/rbac-check.ts +244 -0
  580. package/src/middleware/twofa-presets.ts +224 -0
  581. package/src/models/DecodedAccessToken.ts +17 -0
  582. package/src/models/SessionModel.ts +258 -0
  583. package/src/pages/admin-login/page.tsx +229 -0
  584. package/src/pages/admin-roles/RolesAdminPage.tsx +357 -0
  585. package/src/pages/admin-roles/index.ts +9 -0
  586. package/src/pages/admin-roles/modals.tsx +469 -0
  587. package/src/pages/client-admin/ClientSiteAdminPage.tsx +380 -0
  588. package/src/pages/client-admin/index.ts +33 -0
  589. package/src/pages/login/page.tsx +463 -0
  590. package/src/pages/profile/EnhancedProfilePage.tsx +479 -0
  591. package/src/pages/profile/index.ts +9 -0
  592. package/src/pages/profile/page.tsx +166 -0
  593. package/src/pages/recovery/page.tsx +234 -0
  594. package/src/pages/roles/MyRolesPage.tsx +211 -0
  595. package/src/pages/roles/components.tsx +294 -0
  596. package/src/pages/roles/index.ts +17 -0
  597. package/src/pages/security/EnhancedSecurityPage.tsx +574 -0
  598. package/src/pages/security/index.ts +9 -0
  599. package/src/pages/security/page.tsx +507 -0
  600. package/src/pages/settings/EnhancedSettingsPage.tsx +642 -0
  601. package/src/pages/settings/index.ts +9 -0
  602. package/src/pages/settings/page.tsx +47 -0
  603. package/src/pages/showcase/ShowcasePage.tsx +530 -0
  604. package/src/pages/showcase/index.ts +13 -0
  605. package/src/pages/test-env/EmergencyLogoutPage.tsx +179 -0
  606. package/src/pages/test-env/JwtInspectPage.tsx +418 -0
  607. package/src/pages/test-env/RefreshTokenPage.tsx +155 -0
  608. package/src/pages/test-env/TestEnvPage.tsx +116 -0
  609. package/src/pages/test-env/index.ts +25 -0
  610. package/src/pages/verify-code/page.tsx +648 -0
  611. package/src/routes/account/index.ts +32 -0
  612. package/src/routes/account/masked-info.ts +37 -0
  613. package/src/routes/account/send-code.ts +40 -0
  614. package/src/routes/account/update-phone.ts +13 -0
  615. package/src/routes/account/verify-email.ts +41 -0
  616. package/src/routes/account/verify-sms.ts +41 -0
  617. package/src/routes/auth/index.ts +23 -0
  618. package/src/routes/auth/logout.ts +127 -0
  619. package/src/routes/auth/nextauth.ts +71 -0
  620. package/src/routes/auth/refresh.ts +54 -0
  621. package/src/routes/auth/session.ts +193 -0
  622. package/src/routes/auth/settings.ts +75 -0
  623. package/src/routes/auth/viability.ts +220 -0
  624. package/src/routes/index.ts +18 -0
  625. package/src/routes/session/index.ts +7 -0
  626. package/src/routes/session/refresh-viability.ts +17 -0
  627. package/src/services/signalrActivityService.ts +258 -0
  628. package/src/stores/authStore.ts +1904 -0
  629. package/src/templates/instrumentation.ts +41 -0
  630. package/src/theme/ThemeProvider.tsx +39 -0
  631. package/src/theme/default.ts +33 -0
  632. package/src/theme/index.ts +31 -0
  633. package/src/theme/types.ts +69 -0
  634. package/src/theme/useTheme.ts +57 -0
  635. package/src/theme/utils.ts +40 -0
  636. package/src/types/api.ts +13 -0
  637. package/src/types/auth.d.ts +15 -0
  638. package/src/types/auth.ts +22 -0
  639. package/src/types/logging.ts +11 -0
  640. package/src/types/next-auth.d.ts +15 -0
  641. package/src/types/recovery.ts +54 -0
  642. package/src/types/security.ts +1 -0
  643. package/src/utils/api.ts +353 -0
  644. package/src/utils/circuitBreaker.ts +40 -0
  645. package/src/utils/error-message.ts +108 -0
  646. package/src/utils/layout/reservedSpace.ts +124 -0
  647. package/src/utils/logout.ts +30 -0
  648. package/src/vibe/client.ts +590 -0
  649. package/src/vibe/errors.ts +185 -0
  650. package/src/vibe/generic.ts +429 -0
  651. package/src/vibe/hooks/index.ts +367 -0
  652. package/src/vibe/index.ts +121 -0
  653. package/src/vibe/sessions.ts +551 -0
  654. package/src/vibe/types.ts +577 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Auth Callbacks - Public Exports
3
+ */
4
+
5
+ export { jwtCallback } from './jwt';
6
+ export { sessionCallback } from './session';
7
+ export { signInCallback } from './signin';
@@ -0,0 +1,382 @@
1
+ /**
2
+ * JWT Callback
3
+ *
4
+ * Minimal token strategy - only store redisSessionId in JWT.
5
+ * All session data lives in Redis, not in the browser cookie.
6
+ *
7
+ * HANDLES:
8
+ * - Initial sign-in (credentials): Store redisSessionId from authorize()
9
+ * - Initial sign-in (OAuth): Register with IDP, create session, store redisSessionId
10
+ * - Subsequent requests: Validate session exists, return token
11
+ *
12
+ * @version 1.0.0
13
+ * @since auth-refactor-2026-01
14
+ */
15
+
16
+ import type { JWT } from 'next-auth/jwt';
17
+ import type { User, Account } from 'next-auth';
18
+ import { createHmac } from 'crypto';
19
+ import { createSession, getSession } from '../../lib/session-store';
20
+ import { getIDPClientConfig } from '../../lib/idp-client-config';
21
+ import { idpOAuthCallback } from '../utils/idp-client';
22
+ import {
23
+ decodeIdpAccessToken,
24
+ extractAmrFromToken,
25
+ expClaimToMs,
26
+ extractKidFromToken,
27
+ } from '../utils/token-utils';
28
+ // NOTE: Using any for sessionData until Phase 3 normalizes types
29
+
30
+ // ============================================================================
31
+ // VIBE ROLE FETCHING
32
+ // ============================================================================
33
+
34
+ /**
35
+ * Generate HMAC signature for Vibe API request.
36
+ */
37
+ function generateVibeSignature(
38
+ endpoint: string,
39
+ clientId: string,
40
+ timestamp: number
41
+ ): string {
42
+ const signingKey = process.env.VIBE_SIGNING_KEY;
43
+ if (!signingKey) {
44
+ return '';
45
+ }
46
+
47
+ const stringToSign = `${timestamp}|GET|${endpoint}|${clientId}`;
48
+ return createHmac('sha256', Buffer.from(signingKey, 'base64'))
49
+ .update(stringToSign)
50
+ .digest('base64');
51
+ }
52
+
53
+ /**
54
+ * Fetch user's roles from Vibe API.
55
+ * Returns empty array on failure (non-blocking).
56
+ * Uses HMAC signature for authentication when signing key is configured.
57
+ */
58
+ async function fetchVibeRoles(userId: string, clientId: string): Promise<string[]> {
59
+ const vibeApiUrl = process.env.VIBE_API_URL;
60
+ if (!vibeApiUrl) {
61
+ return [];
62
+ }
63
+
64
+ const endpoint = `/api/v1/users/${userId}/roles`;
65
+ const timestamp = Math.floor(Date.now() / 1000);
66
+ const signature = generateVibeSignature(endpoint, clientId, timestamp);
67
+
68
+ // Build headers with optional signature
69
+ const headers: Record<string, string> = {
70
+ 'Accept': 'application/json',
71
+ 'X-Client-Id': clientId,
72
+ 'X-Vibe-Client-Id': clientId,
73
+ };
74
+
75
+ if (signature) {
76
+ headers['X-Vibe-Timestamp'] = String(timestamp);
77
+ headers['X-Vibe-Signature'] = signature;
78
+ }
79
+
80
+ try {
81
+ const response = await fetch(
82
+ `${vibeApiUrl}${endpoint}`,
83
+ {
84
+ method: 'GET',
85
+ headers,
86
+ // 2 second timeout
87
+ signal: AbortSignal.timeout(2000),
88
+ }
89
+ );
90
+
91
+ if (!response.ok) {
92
+ console.warn('[JWT_CALLBACK] Failed to fetch Vibe roles:', response.status);
93
+ return [];
94
+ }
95
+
96
+ const data = await response.json();
97
+ const roles = data.roles?.map((r: any) => r.role_name || r) || [];
98
+ console.log('[JWT_CALLBACK] Fetched Vibe roles:', roles);
99
+ return roles;
100
+ } catch (error) {
101
+ console.warn('[JWT_CALLBACK] Error fetching Vibe roles (continuing with IDP roles only):', error);
102
+ return [];
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Merge IDP roles with Vibe roles, deduplicating.
108
+ */
109
+ function mergeRoles(idpRoles: string[], vibeRoles: string[]): string[] {
110
+ return [...new Set([...idpRoles, ...vibeRoles])];
111
+ }
112
+
113
+ // ============================================================================
114
+ // TYPES
115
+ // ============================================================================
116
+
117
+ interface JwtCallbackParams {
118
+ token: JWT;
119
+ user?: User | any;
120
+ account?: Account | null;
121
+ trigger?: 'signIn' | 'signUp' | 'update';
122
+ }
123
+
124
+ interface JwtCallbackResult extends JWT {
125
+ /** Redis session ID - the key to look up session data */
126
+ redisSessionId?: string;
127
+ /** User ID from IDP */
128
+ sub: string;
129
+ /** Error code if session validation failed */
130
+ error?: string;
131
+ /** Flag for OAuth users who need immediate 2FA redirect */
132
+ requiresTwoFactorRedirect?: boolean;
133
+ }
134
+
135
+ // ============================================================================
136
+ // JWT CALLBACK
137
+ // ============================================================================
138
+
139
+ /**
140
+ * JWT callback - builds the NextAuth JWT token.
141
+ *
142
+ * MINIMAL TOKEN STRATEGY:
143
+ * - Only store redisSessionId (key to Redis session)
144
+ * - All tokens and user data live in Redis
145
+ * - Browser cookie stays small and secure
146
+ *
147
+ * @param params - JWT callback parameters from NextAuth
148
+ * @returns JWT payload to store in browser cookie
149
+ */
150
+ export async function jwtCallback({
151
+ token,
152
+ user,
153
+ account,
154
+ trigger,
155
+ }: JwtCallbackParams): Promise<JwtCallbackResult> {
156
+ console.log('[JWT_CALLBACK] Called with:', {
157
+ trigger,
158
+ hasAccount: !!account,
159
+ provider: account?.provider,
160
+ hasUser: !!user,
161
+ userEmail: user?.email,
162
+ existingRedisSessionId: token?.redisSessionId ? 'yes' : 'no',
163
+ });
164
+
165
+ // -------------------------------------------------------------------------
166
+ // OAuth Sign-In: Register with IDP and create session
167
+ // -------------------------------------------------------------------------
168
+
169
+ if (account && account.provider !== 'credentials') {
170
+ console.log('[JWT_CALLBACK] Handling OAuth sign-in for provider:', account.provider);
171
+ return handleOAuthSignIn(token, user, account);
172
+ }
173
+
174
+ // -------------------------------------------------------------------------
175
+ // Credentials Sign-In: Session already created in authorize()
176
+ // -------------------------------------------------------------------------
177
+
178
+ if (user && (user as any).redisSessionId) {
179
+ // Credentials authorize() returns redisSessionId
180
+ const redisSessionId = (user as any).redisSessionId;
181
+
182
+ return {
183
+ ...token,
184
+ redisSessionId,
185
+ sub: user.id || token.sub || 'unknown',
186
+ };
187
+ }
188
+
189
+ // -------------------------------------------------------------------------
190
+ // Subsequent Requests: Validate session exists
191
+ // -------------------------------------------------------------------------
192
+
193
+ const redisSessionId = (user as any)?.redisSessionId || token?.redisSessionId || token?.redisSessionId;
194
+
195
+ if (!redisSessionId) {
196
+ return { ...token, error: 'NoSession', sub: token.sub || 'unknown' };
197
+ }
198
+
199
+ // Validate session still exists in Redis
200
+ try {
201
+ const sessionData = await getSession(redisSessionId as string);
202
+
203
+ if (!sessionData) {
204
+ // Session expired or deleted
205
+ return { ...token, error: 'SessionNotFound', sub: token.sub || 'unknown' };
206
+ }
207
+
208
+ // Check if refresh token has expired (session should be terminated)
209
+ if (sessionData.idpRefreshTokenExpires && Date.now() >= sessionData.idpRefreshTokenExpires) {
210
+ return { ...token, error: 'RefreshTokenExpired', sub: token.sub || 'unknown' };
211
+ }
212
+
213
+ // Check if MFA has expired (requires step-up authentication)
214
+ if (sessionData.mfaExpiresAt && Date.now() > sessionData.mfaExpiresAt) {
215
+ return {
216
+ ...token,
217
+ redisSessionId,
218
+ sub: sessionData.userId,
219
+ error: 'MfaExpired',
220
+ };
221
+ }
222
+ } catch (error) {
223
+ console.error('[JWT_CALLBACK] Session validation error:', error);
224
+ return { ...token, error: 'SessionError', sub: token.sub || 'unknown' };
225
+ }
226
+
227
+ // Session is valid - return minimal token
228
+ return {
229
+ ...token,
230
+ redisSessionId,
231
+ sub: token.sub || 'unknown',
232
+ };
233
+ }
234
+
235
+ // ============================================================================
236
+ // OAUTH SIGN-IN HANDLER
237
+ // ============================================================================
238
+
239
+ /**
240
+ * Handle OAuth sign-in by registering with IDP and creating session.
241
+ */
242
+ async function handleOAuthSignIn(
243
+ token: JWT,
244
+ user: User | any,
245
+ account: Account
246
+ ): Promise<JwtCallbackResult> {
247
+ console.log('[JWT_CALLBACK] handleOAuthSignIn starting for:', {
248
+ provider: account.provider,
249
+ email: user?.email,
250
+ providerAccountId: account.providerAccountId,
251
+ });
252
+
253
+ try {
254
+ // Call IDP to register/authenticate OAuth user
255
+ const idpResult = await idpOAuthCallback({
256
+ provider: account.provider,
257
+ providerAccountId: account.providerAccountId,
258
+ email: user?.email || '',
259
+ name: user?.name || '',
260
+ image: user?.image || '',
261
+ accessToken: account.access_token,
262
+ refreshToken: account.refresh_token,
263
+ expiresAt: account.expires_at,
264
+ });
265
+
266
+ // Build session data using normalized field names
267
+ let sessionData: any;
268
+ let mfaVerified = false;
269
+
270
+ if (idpResult.success && idpResult.data?.accessToken) {
271
+ // IDP integration succeeded - we have IDP tokens
272
+ const decoded = decodeIdpAccessToken(idpResult.data.accessToken);
273
+ const amrClaims = decoded ? extractAmrFromToken(decoded) : [];
274
+ const acrLevel = decoded?.acr || '1';
275
+
276
+ // Extract kid from JWT header (CRITICAL: different from client_id in payload)
277
+ const bearerKeyId = extractKidFromToken(idpResult.data.accessToken);
278
+ if (bearerKeyId) {
279
+ console.log('[JWT_CALLBACK] Extracted bearerKeyId (kid) from JWT header:', bearerKeyId);
280
+ } else {
281
+ console.warn('[JWT_CALLBACK] No kid found in JWT header');
282
+ }
283
+
284
+ // Check if MFA is required for this client
285
+ try {
286
+ const clientConfig = await getIDPClientConfig();
287
+ const require2FA = clientConfig?.authSettings?.require2FA ?? true;
288
+ mfaVerified = !require2FA; // If MFA not required, mark as verified
289
+ } catch {
290
+ // Default to requiring MFA if config unavailable
291
+ mfaVerified = false;
292
+ }
293
+
294
+ sessionData = {
295
+ userId: idpResult.data.user?.userId?.toString() || account.providerAccountId,
296
+ email: idpResult.data.user?.email || user?.email || '',
297
+ name: idpResult.data.user?.fullName || user?.name || '',
298
+ roles: idpResult.data.user?.roles || [],
299
+ // IDP tokens (normalized names)
300
+ idpAccessToken: idpResult.data.accessToken,
301
+ idpRefreshToken: idpResult.data.refreshToken,
302
+ idpAccessTokenExpires: decoded?.exp ? expClaimToMs(decoded.exp) : Date.now() + 3600000,
303
+ decodedAccessToken: decoded || undefined,
304
+ // Bearer key ID from JWT header (NOT client_id from payload)
305
+ bearerKeyId,
306
+ // MFA state (normalized names)
307
+ mfaVerified,
308
+ authenticationMethods: amrClaims,
309
+ authenticationLevel: acrLevel,
310
+ // OAuth provider info (normalized names)
311
+ oauthProvider: account.provider,
312
+ oauthProviderToken: account.access_token,
313
+ oauthProviderRefreshToken: account.refresh_token,
314
+ // Multi-tenant info
315
+ idpClientId: decoded?.client_id,
316
+ merchantId: decoded?.merchant_id,
317
+ };
318
+ } else {
319
+ // IDP integration failed - create OAuth-only session
320
+ // This allows OAuth login to work even if IDP is unavailable
321
+ mfaVerified = true; // OAuth IS multi-factor (Google/Microsoft handle MFA)
322
+ sessionData = {
323
+ userId: account.providerAccountId,
324
+ email: user?.email || '',
325
+ name: user?.name || '',
326
+ roles: [],
327
+ mfaVerified: true, // OAuth IS multi-factor
328
+ oauthProvider: account.provider,
329
+ oauthProviderToken: account.access_token,
330
+ oauthProviderRefreshToken: account.refresh_token,
331
+ idpAccessTokenExpires: account.expires_at
332
+ ? account.expires_at * 1000
333
+ : Date.now() + 3600000,
334
+ };
335
+ }
336
+
337
+ // -------------------------------------------------------------------------
338
+ // ROLE MERGING: Fetch Vibe roles and merge with IDP roles
339
+ // -------------------------------------------------------------------------
340
+ const clientId = sessionData.idpClientId || process.env.IDP_CLIENT_ID || '';
341
+ if (clientId && sessionData.userId) {
342
+ const vibeRoles = await fetchVibeRoles(sessionData.userId, clientId);
343
+ // SECURITY: Filter out protected IDP-level role prefixes to prevent injection
344
+ const safeVibeRoles = vibeRoles.filter(r => !r.startsWith('payez_'));
345
+ const idpRoles = sessionData.roles || [];
346
+ sessionData.roles = mergeRoles(idpRoles, safeVibeRoles);
347
+ console.log('[JWT_CALLBACK] Merged roles:', {
348
+ idpRoles,
349
+ vibeRoles,
350
+ safeVibeRoles,
351
+ merged: sessionData.roles,
352
+ });
353
+ }
354
+
355
+ // Create Redis session
356
+ console.log('[JWT_CALLBACK] Creating Redis session for:', {
357
+ userId: sessionData.userId,
358
+ email: sessionData.email,
359
+ mfaVerified: sessionData.mfaVerified,
360
+ roles: sessionData.roles,
361
+ });
362
+
363
+ const redisSessionId = await createSession(sessionData);
364
+
365
+ console.log('[JWT_CALLBACK] Redis session created:', {
366
+ redisSessionId: redisSessionId ? redisSessionId.substring(0, 8) + '...' : 'NONE',
367
+ });
368
+
369
+ // Check if immediate MFA redirect is needed
370
+ const needsImmediateTwoFactor = !mfaVerified;
371
+
372
+ return {
373
+ ...token,
374
+ redisSessionId,
375
+ sub: sessionData.userId,
376
+ requiresTwoFactorRedirect: needsImmediateTwoFactor,
377
+ };
378
+ } catch (error) {
379
+ console.error('[JWT_CALLBACK] handleOAuthSignIn FAILED:', error);
380
+ return { ...token, error: 'OAuthSignInFailed', sub: token.sub || 'unknown' };
381
+ }
382
+ }
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Session Callback
3
+ *
4
+ * Builds the NextAuth session from Redis session data.
5
+ * The JWT only contains redisSessionId - all user data comes from Redis.
6
+ *
7
+ * FLOW:
8
+ * 1. Extract redisSessionId from JWT token
9
+ * 2. Fetch session data from Redis
10
+ * 3. Build NextAuth session with user info
11
+ *
12
+ * @version 1.0.0
13
+ * @since auth-refactor-2026-01
14
+ */
15
+
16
+ import type { Session } from 'next-auth';
17
+ import type { JWT } from 'next-auth/jwt';
18
+ import { getSession } from '../../lib/session-store';
19
+ // NOTE: Using SessionData from models until Phase 3 normalizes names
20
+ import type { SessionData } from '../../models/SessionModel';
21
+
22
+ // ============================================================================
23
+ // TYPES
24
+ // ============================================================================
25
+
26
+ interface SessionCallbackParams {
27
+ session: Session;
28
+ token: JWT & {
29
+ /** Redis session ID - the key to look up session data */
30
+ redisSessionId?: string;
31
+ error?: string;
32
+ };
33
+ }
34
+
35
+ interface AppSessionUser {
36
+ id: string;
37
+ email: string;
38
+ name?: string;
39
+ roles: string[];
40
+ // MFA status
41
+ twoFactorSessionVerified: boolean;
42
+ requiresTwoFactor: boolean;
43
+ // MFA claims from IDP token
44
+ authenticationMethods?: string[];
45
+ authenticationLevel?: string;
46
+ mfaCompletedAt?: number;
47
+ mfaExpiresAt?: number;
48
+ mfaValidityHours?: number;
49
+ // OAuth provider info
50
+ oauthProvider?: string;
51
+ // Multi-tenant IDP info
52
+ idpClientId?: string;
53
+ merchantId?: string;
54
+ // JWT signing key (from header, NOT client_id from payload)
55
+ bearerKeyId?: string;
56
+ }
57
+
58
+ interface AppSession extends Omit<Session, 'user'> {
59
+ user: AppSessionUser;
60
+ sessionToken?: string;
61
+ accessToken?: string;
62
+ refreshToken?: string;
63
+ accessTokenExpires?: number;
64
+ error?: string;
65
+ }
66
+
67
+ // ============================================================================
68
+ // SESSION CALLBACK
69
+ // ============================================================================
70
+
71
+ /**
72
+ * Session callback - builds NextAuth session from Redis.
73
+ *
74
+ * This callback is called whenever getSession() or useSession() is used.
75
+ * It fetches the full session from Redis and exposes it to the client.
76
+ *
77
+ * @param params - Session callback parameters from NextAuth
78
+ * @returns AppSession with user data from Redis
79
+ */
80
+ export async function sessionCallback({
81
+ session,
82
+ token,
83
+ }: SessionCallbackParams): Promise<AppSession> {
84
+ // Support both field names: sessionToken (auth.ts JWT) and redisSessionId (legacy)
85
+ const redisSessionId = (token as any)?.sessionToken || token?.redisSessionId;
86
+
87
+ console.log('[SESSION_CALLBACK] Entry:', {
88
+ hasToken: !!token,
89
+ redisSessionId: redisSessionId || 'MISSING',
90
+ tokenError: token?.error || 'none',
91
+ tokenKeys: token ? Object.keys(token) : [],
92
+ });
93
+
94
+ // -------------------------------------------------------------------------
95
+ // Handle Token Errors
96
+ // -------------------------------------------------------------------------
97
+
98
+ if (token.error) {
99
+ console.log('[SESSION_CALLBACK] Token has error:', token.error);
100
+ // Special case: MFA expired - return partial session for step-up flow
101
+ if (token.error === 'MfaExpired' && redisSessionId) {
102
+ const sessionData = await safeGetSession(redisSessionId as string);
103
+ if (sessionData) {
104
+ return {
105
+ ...session,
106
+ user: {
107
+ id: sessionData.userId,
108
+ email: sessionData.email,
109
+ name: sessionData.name,
110
+ roles: sessionData.roles || [],
111
+ twoFactorSessionVerified: false,
112
+ requiresTwoFactor: true,
113
+ authenticationMethods: sessionData.authenticationMethods,
114
+ authenticationLevel: sessionData.authenticationLevel,
115
+ mfaExpiresAt: sessionData.mfaExpiresAt,
116
+ },
117
+ sessionToken: redisSessionId as string,
118
+ accessToken: sessionData.idpAccessToken,
119
+ refreshToken: sessionData.idpRefreshToken,
120
+ error: 'MfaExpired',
121
+ };
122
+ }
123
+ }
124
+
125
+ // For other errors, try to recover session data if possible
126
+ if (redisSessionId) {
127
+ const sessionData = await safeGetSession(redisSessionId as string);
128
+ if (sessionData) {
129
+ return buildSessionFromRedis(session, redisSessionId as string, sessionData);
130
+ }
131
+ }
132
+
133
+ // No recovery possible - return error session
134
+ return buildErrorSession(session, token.error);
135
+ }
136
+
137
+ // -------------------------------------------------------------------------
138
+ // Validate Session Token
139
+ // -------------------------------------------------------------------------
140
+
141
+ if (!redisSessionId) {
142
+ console.log('[SESSION_CALLBACK] No redisSessionId - returning error session');
143
+ return buildErrorSession(session, 'NoSessionToken');
144
+ }
145
+
146
+ // -------------------------------------------------------------------------
147
+ // Fetch Session from Redis
148
+ // -------------------------------------------------------------------------
149
+
150
+ const sessionData = await safeGetSession(redisSessionId as string);
151
+
152
+ if (!sessionData) {
153
+ console.log('[SESSION_CALLBACK] Redis session not found for:', redisSessionId);
154
+ return buildErrorSession(session, 'SessionNotFound');
155
+ }
156
+
157
+ console.log('[SESSION_CALLBACK] Redis session found:', {
158
+ userId: sessionData.userId,
159
+ email: sessionData.email,
160
+ roles: sessionData.roles,
161
+ hasAccessToken: !!sessionData.idpAccessToken,
162
+ });
163
+
164
+ const result = buildSessionFromRedis(session, redisSessionId as string, sessionData);
165
+ console.log('[SESSION_CALLBACK] Returning:', {
166
+ userId: result.user.id,
167
+ roles: result.user.roles,
168
+ hasAccessToken: !!result.accessToken,
169
+ });
170
+ return result;
171
+ }
172
+
173
+ // ============================================================================
174
+ // HELPER FUNCTIONS
175
+ // ============================================================================
176
+
177
+ /**
178
+ * Safely fetch session from Redis, returning null on error.
179
+ */
180
+ async function safeGetSession(
181
+ sessionId: string
182
+ ): Promise<SessionData | null> {
183
+ try {
184
+ return await getSession(sessionId);
185
+ } catch {
186
+ return null;
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Build complete session from Redis data.
192
+ * Uses normalized field names from SessionData.
193
+ */
194
+ function buildSessionFromRedis(
195
+ session: Session,
196
+ sessionId: string,
197
+ data: SessionData
198
+ ): AppSession {
199
+ return {
200
+ ...session,
201
+ user: {
202
+ id: data.userId,
203
+ email: data.email,
204
+ name: data.name,
205
+ roles: data.roles || [],
206
+ // MFA state (normalized field name)
207
+ twoFactorSessionVerified: data.mfaVerified,
208
+ requiresTwoFactor: !data.mfaVerified,
209
+ authenticationMethods: data.authenticationMethods,
210
+ authenticationLevel: data.authenticationLevel,
211
+ mfaCompletedAt: data.mfaCompletedAt,
212
+ mfaExpiresAt: data.mfaExpiresAt,
213
+ mfaValidityHours: data.mfaValidityHours,
214
+ oauthProvider: data.oauthProvider,
215
+ idpClientId: data.idpClientId,
216
+ merchantId: data.merchantId,
217
+ // Bearer key ID from JWT header (may be undefined for old sessions)
218
+ bearerKeyId: data.bearerKeyId,
219
+ },
220
+ sessionToken: sessionId,
221
+ // IDP tokens (normalized field names)
222
+ accessToken: data.idpAccessToken,
223
+ refreshToken: data.idpRefreshToken,
224
+ accessTokenExpires: data.idpAccessTokenExpires,
225
+ };
226
+ }
227
+
228
+ /**
229
+ * Build error session with empty user.
230
+ */
231
+ function buildErrorSession(session: Session, error: string): AppSession {
232
+ return {
233
+ ...session,
234
+ user: {
235
+ id: '',
236
+ email: '',
237
+ roles: [],
238
+ twoFactorSessionVerified: false,
239
+ requiresTwoFactor: false,
240
+ },
241
+ error,
242
+ };
243
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * SignIn Callback
3
+ *
4
+ * Handles post-authentication actions like 2FA redirect.
5
+ * Called after credentials or OAuth authentication succeeds.
6
+ *
7
+ * @version 1.0.0
8
+ * @since auth-refactor-2026-01
9
+ */
10
+
11
+ import type { User, Account } from 'next-auth';
12
+
13
+ // ============================================================================
14
+ // SIGNIN CALLBACK
15
+ // ============================================================================
16
+
17
+ /**
18
+ * SignIn callback - handle 2FA redirect for OAuth users.
19
+ *
20
+ * When require2FA is true for the client, OAuth users need to be
21
+ * redirected to the verify-code page immediately after OAuth login.
22
+ *
23
+ * @param params - SignIn callback parameters from NextAuth
24
+ * @returns true to allow sign-in, or a URL string to redirect
25
+ */
26
+ export async function signInCallback({
27
+ user,
28
+ account,
29
+ }: {
30
+ user: User | any;
31
+ account: Account | null;
32
+ }): Promise<boolean | string> {
33
+ // Only handle OAuth providers (credentials flow handles 2FA separately)
34
+ if (!account?.provider || account.provider === 'credentials') {
35
+ return true;
36
+ }
37
+
38
+ // Check if OAuth user needs 2FA redirect
39
+ const token = user as any;
40
+ if (token?.requiresTwoFactorRedirect) {
41
+ // Preserve the original callback URL through 2FA flow
42
+ const originalCallbackUrl = (account as any)?.callbackUrl || '/';
43
+
44
+ // Don't redirect back to auth pages after 2FA
45
+ const safeCallbackUrl = originalCallbackUrl.startsWith('/account-auth/')
46
+ ? '/'
47
+ : originalCallbackUrl;
48
+
49
+ const encodedCallback = encodeURIComponent(safeCallbackUrl);
50
+
51
+ // Return redirect URL - NextAuth will redirect here instead of completing sign-in
52
+ return `/account-auth/verify-code?callbackUrl=${encodedCallback}`;
53
+ }
54
+
55
+ return true;
56
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Auth Events - Public Exports
3
+ */
4
+
5
+ export { handleSignOut } from './signout';