@payez/next-mvp 4.0.1 → 4.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/auth-handler.d.ts +66 -0
- package/dist/api/auth-handler.js +397 -0
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.js +19 -0
- package/dist/api-handlers/account/change-password.d.ts +9 -0
- package/dist/api-handlers/account/change-password.js +110 -0
- package/dist/api-handlers/account/masked-info.d.ts +2 -0
- package/dist/api-handlers/account/masked-info.js +41 -0
- package/dist/api-handlers/account/profile.d.ts +3 -0
- package/dist/api-handlers/account/profile.js +63 -0
- package/dist/api-handlers/account/recovery/initiate.d.ts +2 -0
- package/dist/api-handlers/account/recovery/initiate.js +26 -0
- package/dist/api-handlers/account/recovery/send-code.d.ts +2 -0
- package/dist/api-handlers/account/recovery/send-code.js +28 -0
- package/dist/api-handlers/account/recovery/verify-code.d.ts +2 -0
- package/dist/api-handlers/account/recovery/verify-code.js +28 -0
- package/dist/api-handlers/account/reset-password.d.ts +2 -0
- package/dist/api-handlers/account/reset-password.js +26 -0
- package/dist/api-handlers/account/send-code.d.ts +24 -0
- package/dist/api-handlers/account/send-code.js +60 -0
- package/dist/api-handlers/account/update-phone.d.ts +27 -0
- package/dist/api-handlers/account/update-phone.js +64 -0
- package/dist/api-handlers/account/validate-password.d.ts +17 -0
- package/dist/api-handlers/account/validate-password.js +81 -0
- package/dist/api-handlers/account/verify-email.d.ts +26 -0
- package/dist/api-handlers/account/verify-email.js +106 -0
- package/dist/api-handlers/account/verify-sms.d.ts +26 -0
- package/dist/api-handlers/account/verify-sms.js +106 -0
- package/dist/api-handlers/admin/analytics.d.ts +19 -0
- package/dist/api-handlers/admin/analytics.js +378 -0
- package/dist/api-handlers/admin/audit.d.ts +19 -0
- package/dist/api-handlers/admin/audit.js +213 -0
- package/dist/api-handlers/admin/index.d.ts +21 -0
- package/dist/api-handlers/admin/index.js +42 -0
- package/dist/api-handlers/admin/redis-sessions.d.ts +35 -0
- package/dist/api-handlers/admin/redis-sessions.js +203 -0
- package/dist/api-handlers/admin/sessions.d.ts +20 -0
- package/dist/api-handlers/admin/sessions.js +283 -0
- package/dist/api-handlers/admin/site-logs.d.ts +45 -0
- package/dist/api-handlers/admin/site-logs.js +317 -0
- package/dist/api-handlers/admin/stats.d.ts +20 -0
- package/dist/api-handlers/admin/stats.js +239 -0
- package/dist/api-handlers/admin/users.d.ts +19 -0
- package/dist/api-handlers/admin/users.js +221 -0
- package/dist/api-handlers/admin/vibe-data.d.ts +79 -0
- package/dist/api-handlers/admin/vibe-data.js +267 -0
- package/dist/api-handlers/anon/preferences.d.ts +37 -0
- package/dist/api-handlers/anon/preferences.js +96 -0
- package/dist/api-handlers/auth/jwks.d.ts +2 -0
- package/dist/api-handlers/auth/jwks.js +24 -0
- package/dist/api-handlers/auth/login.d.ts +42 -0
- package/dist/api-handlers/auth/login.js +178 -0
- package/dist/api-handlers/auth/refresh.d.ts +74 -0
- package/dist/api-handlers/auth/refresh.js +633 -0
- package/dist/api-handlers/auth/signout.d.ts +37 -0
- package/dist/api-handlers/auth/signout.js +186 -0
- package/dist/api-handlers/auth/status.d.ts +8 -0
- package/dist/api-handlers/auth/status.js +23 -0
- package/dist/api-handlers/auth/update-session.d.ts +37 -0
- package/dist/api-handlers/auth/update-session.js +93 -0
- package/dist/api-handlers/auth/validate.d.ts +6 -0
- package/dist/api-handlers/auth/validate.js +43 -0
- package/dist/api-handlers/auth/verify-code.d.ts +43 -0
- package/dist/api-handlers/auth/verify-code.js +90 -0
- package/dist/api-handlers/session/refresh-viability.d.ts +14 -0
- package/dist/api-handlers/session/refresh-viability.js +39 -0
- package/dist/api-handlers/session/viability.d.ts +13 -0
- package/dist/api-handlers/session/viability.js +114 -0
- package/dist/api-handlers/test/force-expire.d.ts +23 -0
- package/dist/api-handlers/test/force-expire.js +59 -0
- package/dist/auth/auth-decision.d.ts +39 -0
- package/dist/auth/auth-decision.js +182 -0
- package/dist/auth/better-auth.d.ts +79 -0
- package/dist/auth/better-auth.js +119 -0
- package/dist/auth/route-config.d.ts +66 -0
- package/dist/auth/route-config.js +190 -0
- package/dist/auth/types/auth-types.d.ts +417 -0
- package/dist/auth/types/auth-types.js +53 -0
- package/dist/auth/types/index.d.ts +6 -0
- package/dist/auth/types/index.js +22 -0
- package/dist/auth/unauthenticated-routes.d.ts +1 -0
- package/dist/auth/unauthenticated-routes.js +19 -0
- package/dist/auth/utils/idp-client.d.ts +94 -0
- package/dist/auth/utils/idp-client.js +384 -0
- package/dist/auth/utils/index.d.ts +5 -0
- package/dist/auth/utils/index.js +21 -0
- package/dist/auth/utils/token-utils.d.ts +83 -0
- package/dist/auth/utils/token-utils.js +218 -0
- package/dist/client/AuthContext.d.ts +19 -0
- package/dist/client/AuthContext.js +115 -0
- package/dist/client/better-auth-client.d.ts +1020 -0
- package/dist/client/better-auth-client.js +68 -0
- package/dist/client/fetch-with-auth.d.ts +11 -0
- package/dist/client/fetch-with-auth.js +44 -0
- package/dist/client/fetchWithSession.d.ts +3 -0
- package/dist/client/fetchWithSession.js +24 -0
- package/dist/client/index.d.ts +9 -0
- package/dist/client/index.js +20 -0
- package/dist/client/useAnonSession.d.ts +36 -0
- package/dist/client/useAnonSession.js +99 -0
- package/dist/components/SessionSync.d.ts +13 -0
- package/dist/components/SessionSync.js +121 -0
- package/dist/components/SignalRHealthCheck.d.ts +10 -0
- package/dist/components/SignalRHealthCheck.js +97 -0
- package/dist/components/account/MobileNavDrawer.d.ts +32 -0
- package/dist/components/account/MobileNavDrawer.js +81 -0
- package/dist/components/account/UserAvatarMenu.d.ts +20 -0
- package/dist/components/account/UserAvatarMenu.js +91 -0
- package/dist/components/account/index.d.ts +9 -0
- package/dist/components/account/index.js +13 -0
- package/dist/components/admin/AlertSettingsTab.d.ts +48 -0
- package/dist/components/admin/AlertSettingsTab.js +351 -0
- package/dist/components/admin/AnalyticsTab.d.ts +22 -0
- package/dist/components/admin/AnalyticsTab.js +167 -0
- package/dist/components/admin/DataBrowserTab.d.ts +19 -0
- package/dist/components/admin/DataBrowserTab.js +252 -0
- package/dist/components/admin/LoggingSettingsTab.d.ts +73 -0
- package/dist/components/admin/LoggingSettingsTab.js +339 -0
- package/dist/components/admin/SessionsTab.d.ts +37 -0
- package/dist/components/admin/SessionsTab.js +165 -0
- package/dist/components/admin/StatsTab.d.ts +53 -0
- package/dist/components/admin/StatsTab.js +161 -0
- package/dist/components/admin/VibeAdminContext.d.ts +32 -0
- package/dist/components/admin/VibeAdminContext.js +38 -0
- package/dist/components/admin/VibeAdminLayout.d.ts +11 -0
- package/dist/components/admin/VibeAdminLayout.js +71 -0
- package/dist/components/admin/index.d.ts +29 -0
- package/dist/components/admin/index.js +44 -0
- package/dist/components/auth/FederatedAuthSection.d.ts +8 -0
- package/dist/components/auth/FederatedAuthSection.js +45 -0
- package/dist/components/auth/ModeAwareLoginPage.d.ts +10 -0
- package/dist/components/auth/ModeAwareLoginPage.js +42 -0
- package/dist/components/auth/ModeAwareSignupPage.d.ts +9 -0
- package/dist/components/auth/ModeAwareSignupPage.js +78 -0
- package/dist/components/auth/TraditionalAuthSection.d.ts +14 -0
- package/dist/components/auth/TraditionalAuthSection.js +20 -0
- package/dist/components/recovery/CompleteStep.d.ts +5 -0
- package/dist/components/recovery/CompleteStep.js +8 -0
- package/dist/components/recovery/InitiateRecoveryStep.d.ts +8 -0
- package/dist/components/recovery/InitiateRecoveryStep.js +20 -0
- package/dist/components/recovery/SelectMethodStep.d.ts +8 -0
- package/dist/components/recovery/SelectMethodStep.js +8 -0
- package/dist/components/recovery/SetPasswordStep.d.ts +6 -0
- package/dist/components/recovery/SetPasswordStep.js +20 -0
- package/dist/components/recovery/VerifyCodeStep.d.ts +10 -0
- package/dist/components/recovery/VerifyCodeStep.js +24 -0
- package/dist/components/reserved/ReservedRecoveryWarning.d.ts +38 -0
- package/dist/components/reserved/ReservedRecoveryWarning.js +92 -0
- package/dist/components/reserved/ReservedStatusBox.d.ts +30 -0
- package/dist/components/reserved/ReservedStatusBox.js +71 -0
- package/dist/components/ui/BetaBadge.d.ts +29 -0
- package/dist/components/ui/BetaBadge.js +38 -0
- package/dist/components/ui/Footer.d.ts +37 -0
- package/dist/components/ui/Footer.js +41 -0
- package/dist/config/env.d.ts +66 -0
- package/dist/config/env.js +57 -0
- package/dist/config/logger.d.ts +57 -0
- package/dist/config/logger.js +73 -0
- package/dist/config/logging-config.d.ts +30 -0
- package/dist/config/logging-config.js +122 -0
- package/dist/config/unauthenticated-routes.d.ts +17 -0
- package/dist/config/unauthenticated-routes.js +24 -0
- package/dist/config/vibe-log-transport.d.ts +81 -0
- package/dist/config/vibe-log-transport.js +212 -0
- package/dist/edge/internal-api-url.d.ts +53 -0
- package/dist/edge/internal-api-url.js +63 -0
- package/dist/edge/middleware.d.ts +14 -0
- package/dist/edge/middleware.js +32 -0
- package/dist/hooks/useAuth.d.ts +23 -0
- package/dist/hooks/useAuth.js +83 -0
- package/dist/hooks/useAuthSettings.d.ts +59 -0
- package/dist/hooks/useAuthSettings.js +93 -0
- package/dist/hooks/useAvailableProviders.d.ts +43 -0
- package/dist/hooks/useAvailableProviders.js +112 -0
- package/dist/hooks/usePasswordValidation.d.ts +27 -0
- package/dist/hooks/usePasswordValidation.js +102 -0
- package/dist/hooks/useProfile.d.ts +15 -0
- package/dist/hooks/useProfile.js +59 -0
- package/dist/hooks/usePublicAuthSettings.d.ts +56 -0
- package/dist/hooks/usePublicAuthSettings.js +131 -0
- package/dist/hooks/useSessionExpiration.d.ts +56 -0
- package/dist/hooks/useSessionExpiration.js +72 -0
- package/dist/hooks/useViabilitySession.d.ts +75 -0
- package/dist/hooks/useViabilitySession.js +269 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +53 -0
- package/dist/lib/anon-session.d.ts +74 -0
- package/dist/lib/anon-session.js +169 -0
- package/dist/lib/api-handler.d.ts +123 -0
- package/dist/lib/api-handler.js +478 -0
- package/dist/lib/app-slug.d.ts +95 -0
- package/dist/lib/app-slug.js +172 -0
- package/dist/lib/demo-mode.d.ts +6 -0
- package/dist/lib/demo-mode.js +16 -0
- package/dist/lib/geolocation.d.ts +64 -0
- package/dist/lib/geolocation.js +235 -0
- package/dist/lib/idp-client-config.d.ts +75 -0
- package/dist/lib/idp-client-config.js +425 -0
- package/dist/lib/idp-fetch.d.ts +14 -0
- package/dist/lib/idp-fetch.js +91 -0
- package/dist/lib/internal-api.d.ts +87 -0
- package/dist/lib/internal-api.js +122 -0
- package/dist/lib/jwt-decode-client.d.ts +10 -0
- package/dist/lib/jwt-decode-client.js +46 -0
- package/dist/lib/jwt-decode.d.ts +48 -0
- package/dist/lib/jwt-decode.js +57 -0
- package/dist/lib/rate-limit-service.d.ts +23 -0
- package/dist/lib/rate-limit-service.js +6 -0
- package/dist/lib/redis.d.ts +5 -0
- package/dist/lib/redis.js +28 -0
- package/dist/lib/refresh-token-validator.d.ts +13 -0
- package/dist/lib/refresh-token-validator.js +117 -0
- package/dist/lib/roles.d.ts +145 -0
- package/dist/lib/roles.js +168 -0
- package/dist/lib/secret-validation.d.ts +4 -0
- package/dist/lib/secret-validation.js +14 -0
- package/dist/lib/session-store.d.ts +170 -0
- package/dist/lib/session-store.js +545 -0
- package/dist/lib/session.d.ts +21 -0
- package/dist/lib/session.js +26 -0
- package/dist/lib/site-logger.d.ts +214 -0
- package/dist/lib/site-logger.js +210 -0
- package/dist/lib/standardized-client-api.d.ts +161 -0
- package/dist/lib/standardized-client-api.js +791 -0
- package/dist/lib/startup-init.d.ts +40 -0
- package/dist/lib/startup-init.js +257 -0
- package/dist/lib/test-aware-get-token.d.ts +2 -0
- package/dist/lib/test-aware-get-token.js +86 -0
- package/dist/lib/token-expiry.d.ts +14 -0
- package/dist/lib/token-expiry.js +39 -0
- package/dist/lib/token-lifecycle.d.ts +78 -0
- package/dist/lib/token-lifecycle.js +360 -0
- package/dist/lib/types/api-responses.d.ts +128 -0
- package/dist/lib/types/api-responses.js +171 -0
- package/dist/lib/user-agent-parser.d.ts +50 -0
- package/dist/lib/user-agent-parser.js +220 -0
- package/dist/logging/api/admin-analytics.d.ts +3 -0
- package/dist/logging/api/admin-analytics.js +45 -0
- package/dist/logging/api/audit-log.d.ts +3 -0
- package/dist/logging/api/audit-log.js +52 -0
- package/dist/logging/components/AdminAnalyticsLayout.d.ts +10 -0
- package/dist/logging/components/AdminAnalyticsLayout.js +11 -0
- package/dist/logging/components/AuditLogViewer.d.ts +7 -0
- package/dist/logging/components/AuditLogViewer.js +51 -0
- package/dist/logging/components/ErrorMetricsCard.d.ts +7 -0
- package/dist/logging/components/ErrorMetricsCard.js +16 -0
- package/dist/logging/components/HealthMetricsCard.d.ts +7 -0
- package/dist/logging/components/HealthMetricsCard.js +19 -0
- package/dist/logging/hooks/useAdminAnalytics.d.ts +24 -0
- package/dist/logging/hooks/useAdminAnalytics.js +22 -0
- package/dist/logging/hooks/useAuditLog.d.ts +6 -0
- package/dist/logging/hooks/useAuditLog.js +25 -0
- package/dist/logging/hooks/useErrorMetrics.d.ts +6 -0
- package/dist/logging/hooks/useErrorMetrics.js +38 -0
- package/dist/logging/hooks/useHealthMetrics.d.ts +6 -0
- package/dist/logging/hooks/useHealthMetrics.js +41 -0
- package/dist/logging/index.d.ts +11 -0
- package/dist/logging/index.js +40 -0
- package/dist/logging/types/analytics.d.ts +68 -0
- package/dist/logging/types/analytics.js +3 -0
- package/dist/logging/types/audit.d.ts +29 -0
- package/dist/logging/types/audit.js +2 -0
- package/dist/logging/types/index.d.ts +2 -0
- package/dist/logging/types/index.js +19 -0
- package/dist/middleware/auth-decision.d.ts +33 -0
- package/dist/middleware/auth-decision.js +65 -0
- package/dist/middleware/create-middleware.d.ts +102 -0
- package/dist/middleware/create-middleware.js +469 -0
- package/dist/middleware/rbac-check.d.ts +51 -0
- package/dist/middleware/rbac-check.js +219 -0
- package/dist/middleware/twofa-presets.d.ts +134 -0
- package/dist/middleware/twofa-presets.js +175 -0
- package/dist/models/DecodedAccessToken.d.ts +17 -0
- package/dist/models/DecodedAccessToken.js +2 -0
- package/dist/models/SessionModel.d.ts +122 -0
- package/dist/models/SessionModel.js +136 -0
- package/dist/pages/admin-login/page.d.ts +31 -0
- package/dist/pages/admin-login/page.js +73 -0
- package/dist/pages/admin-page-permissions/PagePermissionsAdminPage.d.ts +18 -0
- package/dist/pages/admin-page-permissions/PagePermissionsAdminPage.js +276 -0
- package/dist/pages/admin-page-permissions/index.d.ts +6 -0
- package/dist/pages/admin-page-permissions/index.js +13 -0
- package/dist/pages/admin-roles/RolesAdminPage.d.ts +16 -0
- package/dist/pages/admin-roles/RolesAdminPage.js +261 -0
- package/dist/pages/admin-roles/index.d.ts +8 -0
- package/dist/pages/admin-roles/index.js +15 -0
- package/dist/pages/admin-roles/modals.d.ts +72 -0
- package/dist/pages/admin-roles/modals.js +154 -0
- package/dist/pages/client-admin/ClientSiteAdminPage.d.ts +79 -0
- package/dist/pages/client-admin/ClientSiteAdminPage.js +179 -0
- package/dist/pages/client-admin/index.d.ts +32 -0
- package/dist/pages/client-admin/index.js +37 -0
- package/dist/pages/coming-soon/page.d.ts +8 -0
- package/dist/pages/coming-soon/page.js +28 -0
- package/dist/pages/login/page.d.ts +22 -0
- package/dist/pages/login/page.js +230 -0
- package/dist/pages/profile/EnhancedProfilePage.d.ts +13 -0
- package/dist/pages/profile/EnhancedProfilePage.js +150 -0
- package/dist/pages/profile/index.d.ts +8 -0
- package/dist/pages/profile/index.js +16 -0
- package/dist/pages/profile/page.d.ts +19 -0
- package/dist/pages/profile/page.js +47 -0
- package/dist/pages/recovery/page.d.ts +1 -0
- package/dist/pages/recovery/page.js +142 -0
- package/dist/pages/roles/MyRolesPage.d.ts +24 -0
- package/dist/pages/roles/MyRolesPage.js +71 -0
- package/dist/pages/roles/components.d.ts +63 -0
- package/dist/pages/roles/components.js +108 -0
- package/dist/pages/roles/index.d.ts +8 -0
- package/dist/pages/roles/index.js +19 -0
- package/dist/pages/security/EnhancedSecurityPage.d.ts +14 -0
- package/dist/pages/security/EnhancedSecurityPage.js +248 -0
- package/dist/pages/security/index.d.ts +8 -0
- package/dist/pages/security/index.js +16 -0
- package/dist/pages/security/page.d.ts +21 -0
- package/dist/pages/security/page.js +212 -0
- package/dist/pages/settings/EnhancedSettingsPage.d.ts +46 -0
- package/dist/pages/settings/EnhancedSettingsPage.js +231 -0
- package/dist/pages/settings/index.d.ts +8 -0
- package/dist/pages/settings/index.js +16 -0
- package/dist/pages/settings/page.d.ts +7 -0
- package/dist/pages/settings/page.js +26 -0
- package/dist/pages/showcase/ShowcasePage.d.ts +13 -0
- package/dist/pages/showcase/ShowcasePage.js +142 -0
- package/dist/pages/showcase/index.d.ts +12 -0
- package/dist/pages/showcase/index.js +17 -0
- package/dist/pages/test-env/EmergencyLogoutPage.d.ts +14 -0
- package/dist/pages/test-env/EmergencyLogoutPage.js +99 -0
- package/dist/pages/test-env/JwtInspectPage.d.ts +14 -0
- package/dist/pages/test-env/JwtInspectPage.js +116 -0
- package/dist/pages/test-env/RefreshTokenPage.d.ts +15 -0
- package/dist/pages/test-env/RefreshTokenPage.js +93 -0
- package/dist/pages/test-env/TestEnvPage.d.ts +13 -0
- package/dist/pages/test-env/TestEnvPage.js +51 -0
- package/dist/pages/test-env/index.d.ts +24 -0
- package/dist/pages/test-env/index.js +32 -0
- package/dist/pages/verify-code/page.d.ts +30 -0
- package/dist/pages/verify-code/page.js +412 -0
- package/dist/routes/account/index.d.ts +28 -0
- package/dist/routes/account/index.js +71 -0
- package/dist/routes/account/masked-info.d.ts +33 -0
- package/dist/routes/account/masked-info.js +39 -0
- package/dist/routes/account/send-code.d.ts +37 -0
- package/dist/routes/account/send-code.js +42 -0
- package/dist/routes/account/update-phone.d.ts +13 -0
- package/dist/routes/account/update-phone.js +17 -0
- package/dist/routes/account/verify-email.d.ts +38 -0
- package/dist/routes/account/verify-email.js +43 -0
- package/dist/routes/account/verify-sms.d.ts +38 -0
- package/dist/routes/account/verify-sms.js +43 -0
- package/dist/routes/auth/index.d.ts +19 -0
- package/dist/routes/auth/index.js +64 -0
- package/dist/routes/auth/logout.d.ts +31 -0
- package/dist/routes/auth/logout.js +98 -0
- package/dist/routes/auth/nextauth.d.ts +22 -0
- package/dist/routes/auth/nextauth.js +40 -0
- package/dist/routes/auth/refresh.d.ts +30 -0
- package/dist/routes/auth/refresh.js +51 -0
- package/dist/routes/auth/session.d.ts +43 -0
- package/dist/routes/auth/session.js +157 -0
- package/dist/routes/auth/settings.d.ts +25 -0
- package/dist/routes/auth/settings.js +55 -0
- package/dist/routes/auth/viability.d.ts +52 -0
- package/dist/routes/auth/viability.js +190 -0
- package/dist/routes/index.d.ts +12 -0
- package/dist/routes/index.js +54 -0
- package/dist/routes/session/index.d.ts +6 -0
- package/dist/routes/session/index.js +10 -0
- package/dist/routes/session/refresh-viability.d.ts +16 -0
- package/dist/routes/session/refresh-viability.js +20 -0
- package/dist/server/auth-guard.d.ts +46 -0
- package/dist/server/auth-guard.js +128 -0
- package/dist/server/auth.d.ts +50 -0
- package/dist/server/auth.js +62 -0
- package/dist/server/decode-session.d.ts +30 -0
- package/dist/server/decode-session.js +78 -0
- package/dist/server/slim-middleware.d.ts +23 -0
- package/dist/server/slim-middleware.js +89 -0
- package/dist/server/with-auth.d.ts +33 -0
- package/dist/server/with-auth.js +59 -0
- package/dist/services/signalrActivityService.d.ts +44 -0
- package/dist/services/signalrActivityService.js +257 -0
- package/dist/stores/authStore.d.ts +154 -0
- package/dist/stores/authStore.js +1527 -0
- package/dist/theme/ThemeProvider.d.ts +14 -0
- package/dist/theme/ThemeProvider.js +28 -0
- package/dist/theme/default.d.ts +8 -0
- package/dist/theme/default.js +33 -0
- package/dist/theme/index.d.ts +15 -0
- package/dist/theme/index.js +25 -0
- package/dist/theme/types.d.ts +56 -0
- package/dist/theme/types.js +8 -0
- package/dist/theme/useTheme.d.ts +60 -0
- package/dist/theme/useTheme.js +63 -0
- package/dist/theme/utils.d.ts +13 -0
- package/dist/theme/utils.js +39 -0
- package/dist/types/api.d.ts +134 -0
- package/dist/types/api.js +44 -0
- package/dist/types/auth.d.ts +19 -0
- package/dist/types/auth.js +2 -0
- package/dist/types/logging.d.ts +42 -0
- package/dist/types/logging.js +2 -0
- package/dist/types/recovery.d.ts +48 -0
- package/dist/types/recovery.js +2 -0
- package/dist/types/security.d.ts +1 -0
- package/dist/types/security.js +2 -0
- package/dist/utils/api.d.ts +85 -0
- package/dist/utils/api.js +287 -0
- package/dist/utils/circuitBreaker.d.ts +43 -0
- package/dist/utils/circuitBreaker.js +91 -0
- package/dist/utils/error-message.d.ts +1 -0
- package/dist/utils/error-message.js +103 -0
- package/dist/utils/layout/reservedSpace.d.ts +59 -0
- package/dist/utils/layout/reservedSpace.js +102 -0
- package/dist/utils/logout.d.ts +14 -0
- package/dist/utils/logout.js +32 -0
- package/dist/vibe/client.d.ts +261 -0
- package/dist/vibe/client.js +445 -0
- package/dist/vibe/enterprise-auth.d.ts +106 -0
- package/dist/vibe/enterprise-auth.js +173 -0
- package/dist/vibe/errors.d.ts +83 -0
- package/dist/vibe/errors.js +146 -0
- package/dist/vibe/generic.d.ts +234 -0
- package/dist/vibe/generic.js +369 -0
- package/dist/vibe/hooks/index.d.ts +169 -0
- package/dist/vibe/hooks/index.js +252 -0
- package/dist/vibe/index.d.ts +25 -0
- package/dist/vibe/index.js +72 -0
- package/dist/vibe/sessions.d.ts +161 -0
- package/dist/vibe/sessions.js +391 -0
- package/dist/vibe/types.d.ts +353 -0
- package/dist/vibe/types.js +315 -0
- package/package.json +1 -1
- package/src/auth/better-auth.ts +2 -2
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session Viability Check API Handler for `@payez/next-mvp`
|
|
4
|
+
*
|
|
5
|
+
* This API route is called by the middleware to securely check if a session is valid.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.GET = GET;
|
|
9
|
+
const server_1 = require("next/server");
|
|
10
|
+
const session_store_1 = require("../../lib/session-store");
|
|
11
|
+
const auth_1 = require("../../server/auth");
|
|
12
|
+
const startup_init_1 = require("../../lib/startup-init");
|
|
13
|
+
const idp_client_config_1 = require("../../lib/idp-client-config");
|
|
14
|
+
async function GET(req) {
|
|
15
|
+
try {
|
|
16
|
+
// Ensure initialization is complete
|
|
17
|
+
if (!process.env.NEXTAUTH_SECRET) {
|
|
18
|
+
try {
|
|
19
|
+
await (0, startup_init_1.ensureInitialized)();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
// Initialization failed - return 503
|
|
23
|
+
console.error('[API Viability] Initialization failed - returning 503');
|
|
24
|
+
return server_1.NextResponse.json({
|
|
25
|
+
error: 'Service Unavailable',
|
|
26
|
+
message: 'Authentication service is not properly configured',
|
|
27
|
+
code: 'AUTH_NOT_INITIALIZED'
|
|
28
|
+
}, { status: 503 });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Double-check after initialization attempt
|
|
32
|
+
if ((0, startup_init_1.isInitializationFailed)()) {
|
|
33
|
+
console.error('[API Viability] Initialization failed - returning 503');
|
|
34
|
+
return server_1.NextResponse.json({
|
|
35
|
+
error: 'Service Unavailable',
|
|
36
|
+
message: 'Authentication service is not properly configured',
|
|
37
|
+
code: 'AUTH_NOT_INITIALIZED'
|
|
38
|
+
}, { status: 503 });
|
|
39
|
+
}
|
|
40
|
+
// Get session from Better Auth
|
|
41
|
+
const betterAuthSession = await (0, auth_1.getSession)(req);
|
|
42
|
+
// Debug logging
|
|
43
|
+
if (!betterAuthSession) {
|
|
44
|
+
console.warn('[VIABILITY] getSession returned null');
|
|
45
|
+
}
|
|
46
|
+
const sessionToken = betterAuthSession?.session?.token;
|
|
47
|
+
if (betterAuthSession && sessionToken) {
|
|
48
|
+
const sessionData = await (0, session_store_1.getSession)(sessionToken);
|
|
49
|
+
if (sessionData) {
|
|
50
|
+
// The session exists in Redis
|
|
51
|
+
// Check if access token is expired (for middleware decision-making)
|
|
52
|
+
const accessTokenExpires = sessionData.idpAccessTokenExpires || 0;
|
|
53
|
+
const accessTokenExpired = accessTokenExpires < Date.now();
|
|
54
|
+
// Get requires2FA from cached client config (not session)
|
|
55
|
+
// This is a client-wide setting from the broker handshake
|
|
56
|
+
let requires2FA = true; // Default to true for security
|
|
57
|
+
try {
|
|
58
|
+
const cachedConfig = await (0, idp_client_config_1.getIDPClientConfig)();
|
|
59
|
+
requires2FA = cachedConfig.authSettings?.require2FA ?? true;
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
console.warn('[API Viability] Could not get client config, defaulting requires2FA to true');
|
|
63
|
+
}
|
|
64
|
+
// CRITICAL: Check if MFA has expired (2FA TTL enforcement)
|
|
65
|
+
// The session may have mfaVerified=true from days ago, but if mfaExpiresAt
|
|
66
|
+
// has passed, we must treat 2FA as incomplete to force re-verification.
|
|
67
|
+
const mfaExpiresAt = sessionData.mfaExpiresAt || 0;
|
|
68
|
+
const mfaExpired = mfaExpiresAt > 0 && mfaExpiresAt < Date.now();
|
|
69
|
+
// Check both field names for compatibility (mfaVerified is the normalized name)
|
|
70
|
+
const sessionMfaComplete = sessionData.mfaVerified ?? sessionData.twoFactorComplete ?? false;
|
|
71
|
+
const effectiveTwoFactorComplete = sessionMfaComplete && !mfaExpired;
|
|
72
|
+
console.log('[VIABILITY] Session 2FA check:', {
|
|
73
|
+
sessionToken: sessionToken.substring(0, 8) + '...',
|
|
74
|
+
mfaVerified: sessionData.mfaVerified,
|
|
75
|
+
twoFactorComplete: sessionData.twoFactorComplete,
|
|
76
|
+
sessionMfaComplete,
|
|
77
|
+
mfaExpired,
|
|
78
|
+
effectiveTwoFactorComplete,
|
|
79
|
+
});
|
|
80
|
+
if (mfaExpired && sessionMfaComplete) {
|
|
81
|
+
console.warn('[API Viability] MFA expired - forcing 2FA re-verification', {
|
|
82
|
+
mfaExpiresAt: new Date(mfaExpiresAt).toISOString(),
|
|
83
|
+
now: new Date().toISOString(),
|
|
84
|
+
hoursExpiredAgo: ((Date.now() - mfaExpiresAt) / (1000 * 60 * 60)).toFixed(1)
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const response = {
|
|
88
|
+
authenticated: true,
|
|
89
|
+
sessionToken, // Include token for middleware tracking
|
|
90
|
+
// 2FA fields - critical for middleware redirect logic
|
|
91
|
+
requires2FA, // From cached client config (client-wide setting)
|
|
92
|
+
twoFactorComplete: effectiveTwoFactorComplete, // From session, BUT respects MFA TTL
|
|
93
|
+
// Token status for refresh decisions
|
|
94
|
+
accessTokenExpired,
|
|
95
|
+
hasRefreshToken: !!sessionData.idpRefreshToken
|
|
96
|
+
};
|
|
97
|
+
return server_1.NextResponse.json(response);
|
|
98
|
+
}
|
|
99
|
+
// CRITICAL: Cookie exists but Redis session is missing (stale cookie state)
|
|
100
|
+
// Return sessionToken so middleware can detect this and clear the stale cookie
|
|
101
|
+
console.warn('[VIABILITY] Stale cookie detected - session not in Redis');
|
|
102
|
+
return server_1.NextResponse.json({
|
|
103
|
+
authenticated: false,
|
|
104
|
+
sessionToken // Include token to enable stale cookie detection
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// If there's no token at all, it's not authenticated
|
|
108
|
+
return server_1.NextResponse.json({ authenticated: false });
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error('[API Viability] Error checking session viability:', error);
|
|
112
|
+
return server_1.NextResponse.json({ authenticated: false }, { status: 500 });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
/**
|
|
3
|
+
* Force-expire access token for testing refresh flow.
|
|
4
|
+
*
|
|
5
|
+
* Sets the access token expiry to 2 minutes in the past,
|
|
6
|
+
* which will trigger a refresh on the next API call.
|
|
7
|
+
*
|
|
8
|
+
* Usage in consuming app:
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // app/api/test/force-expire/route.ts
|
|
11
|
+
* export { POST } from '@payez/next-mvp/api-handlers/test/force-expire';
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare const POST: (req: NextRequest) => Promise<NextResponse<{
|
|
15
|
+
success: boolean;
|
|
16
|
+
error: string;
|
|
17
|
+
}> | NextResponse<{
|
|
18
|
+
success: boolean;
|
|
19
|
+
previous: number | null;
|
|
20
|
+
previousIso: string | null;
|
|
21
|
+
newExpiry: number;
|
|
22
|
+
newExpiryIso: string;
|
|
23
|
+
}>>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POST = void 0;
|
|
4
|
+
const server_1 = require("next/server");
|
|
5
|
+
const auth_1 = require("../../server/auth");
|
|
6
|
+
const session_store_1 = require("../../lib/session-store");
|
|
7
|
+
/**
|
|
8
|
+
* Force-expire access token for testing refresh flow.
|
|
9
|
+
*
|
|
10
|
+
* Sets the access token expiry to 2 minutes in the past,
|
|
11
|
+
* which will trigger a refresh on the next API call.
|
|
12
|
+
*
|
|
13
|
+
* Usage in consuming app:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // app/api/test/force-expire/route.ts
|
|
16
|
+
* export { POST } from '@payez/next-mvp/api-handlers/test/force-expire';
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
const POST = async (req) => {
|
|
20
|
+
try {
|
|
21
|
+
const betterAuthSession = await (0, auth_1.getSession)(req);
|
|
22
|
+
let sessionToken = betterAuthSession?.session?.token;
|
|
23
|
+
if (!sessionToken) {
|
|
24
|
+
const headerSessionToken = req.headers.get('x-session-token') || req.headers.get('X-Session-Token');
|
|
25
|
+
if (headerSessionToken) {
|
|
26
|
+
sessionToken = headerSessionToken;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
console.warn('[TEST_EXPIRE] No session token or X-Session-Token header');
|
|
30
|
+
return server_1.NextResponse.json({ success: false, error: 'No session token' }, { status: 401 });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const session = await (0, session_store_1.getSession)(sessionToken);
|
|
34
|
+
if (!session) {
|
|
35
|
+
return server_1.NextResponse.json({ success: false, error: 'Session not found' }, { status: 404 });
|
|
36
|
+
}
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
const forced = now - (2 * 60 * 1000); // two minutes ago
|
|
39
|
+
const prev = session.idpAccessTokenExpires || null;
|
|
40
|
+
await (0, session_store_1.updateSession)(sessionToken, { idpAccessTokenExpires: forced });
|
|
41
|
+
console.log('[TEST_EXPIRE] Forced access token expiry for session', {
|
|
42
|
+
sessionToken: sessionToken.substring(0, 8) + '...',
|
|
43
|
+
previous: prev ? new Date(prev).toISOString() : null,
|
|
44
|
+
newExpiry: new Date(forced).toISOString()
|
|
45
|
+
});
|
|
46
|
+
return server_1.NextResponse.json({
|
|
47
|
+
success: true,
|
|
48
|
+
previous: prev,
|
|
49
|
+
previousIso: prev ? new Date(prev).toISOString() : null,
|
|
50
|
+
newExpiry: forced,
|
|
51
|
+
newExpiryIso: new Date(forced).toISOString()
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
console.error('[TEST_EXPIRE] Error:', e);
|
|
56
|
+
return server_1.NextResponse.json({ success: false, error: e instanceof Error ? e.message : String(e) }, { status: 500 });
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
exports.POST = POST;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Decision Engine - Pure function for middleware auth flow
|
|
3
|
+
*
|
|
4
|
+
* This module provides a deterministic decision tree for authentication middleware.
|
|
5
|
+
* All auth flow logic is centralized here for testability and maintainability.
|
|
6
|
+
*/
|
|
7
|
+
export interface AuthContext {
|
|
8
|
+
pathname: string;
|
|
9
|
+
isPublicRoute: boolean;
|
|
10
|
+
isLoginPage: boolean;
|
|
11
|
+
searchParams: URLSearchParams;
|
|
12
|
+
sessionPointer: {
|
|
13
|
+
exists: boolean;
|
|
14
|
+
sessionToken?: string;
|
|
15
|
+
expired?: boolean;
|
|
16
|
+
};
|
|
17
|
+
sessionStatus: {
|
|
18
|
+
exists: boolean | null;
|
|
19
|
+
forceInvalid: boolean | null;
|
|
20
|
+
requires2FA: boolean;
|
|
21
|
+
twoFactorComplete: boolean;
|
|
22
|
+
};
|
|
23
|
+
circuitBreakerOpen: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type AuthAction = {
|
|
26
|
+
type: 'allow';
|
|
27
|
+
} | {
|
|
28
|
+
type: 'redirect';
|
|
29
|
+
location: string;
|
|
30
|
+
reason: string;
|
|
31
|
+
clearCookies?: boolean;
|
|
32
|
+
} | {
|
|
33
|
+
type: 'service_error';
|
|
34
|
+
reason: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Main decision function - pure, testable, deterministic
|
|
38
|
+
*/
|
|
39
|
+
export declare function makeAuthDecision(context: AuthContext): AuthAction;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Auth Decision Engine - Pure function for middleware auth flow
|
|
4
|
+
*
|
|
5
|
+
* This module provides a deterministic decision tree for authentication middleware.
|
|
6
|
+
* All auth flow logic is centralized here for testability and maintainability.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.makeAuthDecision = makeAuthDecision;
|
|
10
|
+
/**
|
|
11
|
+
* Main decision function - pure, testable, deterministic
|
|
12
|
+
*/
|
|
13
|
+
function makeAuthDecision(context) {
|
|
14
|
+
const { pathname, isPublicRoute, isLoginPage, searchParams, sessionPointer, sessionStatus, circuitBreakerOpen } = context;
|
|
15
|
+
// SAFEGUARD: Never use auth pages as callback URLs to prevent redirect loops
|
|
16
|
+
const safeCallbackUrl = pathname.startsWith('/account-auth/') ? '/' : pathname;
|
|
17
|
+
// Public routes are allowed, but we need to check login page separately
|
|
18
|
+
if (isPublicRoute && !isLoginPage) {
|
|
19
|
+
// For non-login public routes, check if authenticated user needs 2FA
|
|
20
|
+
if (sessionPointer.exists && sessionStatus.exists && sessionStatus.requires2FA && !sessionStatus.twoFactorComplete) {
|
|
21
|
+
// Skip redirect for verify-code page
|
|
22
|
+
if (pathname === '/account-auth/verify-code') {
|
|
23
|
+
return { type: 'allow' };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return { type: 'allow' };
|
|
27
|
+
}
|
|
28
|
+
// Circuit breaker open - redirect to login with service unavailable
|
|
29
|
+
if (circuitBreakerOpen) {
|
|
30
|
+
if (isLoginPage) {
|
|
31
|
+
return { type: 'allow' }; // Let them see login page
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
type: 'redirect',
|
|
35
|
+
location: '/account-auth/login?error=ServiceUnavailable&reason=CircuitBreakerOpen',
|
|
36
|
+
reason: 'CircuitBreakerOpen',
|
|
37
|
+
clearCookies: true
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// No session pointer (JWT cookie) - need to login
|
|
41
|
+
if (!sessionPointer.exists) {
|
|
42
|
+
if (isLoginPage) {
|
|
43
|
+
return { type: 'allow' };
|
|
44
|
+
}
|
|
45
|
+
// Redirect root to configured URL for unauthenticated users
|
|
46
|
+
if (pathname === '/') {
|
|
47
|
+
const unauthUrl = process.env.UNAUTHENTICATED_REDIRECT_URL || '/account-auth/login';
|
|
48
|
+
return {
|
|
49
|
+
type: 'redirect',
|
|
50
|
+
location: unauthUrl,
|
|
51
|
+
reason: 'unauthenticated_root_redirect'
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
type: 'redirect',
|
|
56
|
+
location: `/account-auth/login?callbackUrl=${encodeURIComponent(safeCallbackUrl)}`,
|
|
57
|
+
reason: 'no_session_pointer'
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// Redis/service errors - can't verify session
|
|
61
|
+
if (sessionStatus.exists === null || sessionStatus.forceInvalid === null) {
|
|
62
|
+
return {
|
|
63
|
+
type: 'service_error',
|
|
64
|
+
reason: 'redis_unavailable'
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// Session force invalidated - need fresh login
|
|
68
|
+
if (sessionStatus.forceInvalid) {
|
|
69
|
+
if (isLoginPage) {
|
|
70
|
+
return { type: 'allow' };
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
type: 'redirect',
|
|
74
|
+
location: `/account-auth/login?callbackUrl=${encodeURIComponent(safeCallbackUrl)}&reason=force_invalidated`,
|
|
75
|
+
reason: 'force_invalidated',
|
|
76
|
+
clearCookies: true
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// Stale session (cookie exists but not in Redis) - need fresh login
|
|
80
|
+
if (!sessionStatus.exists) {
|
|
81
|
+
if (isLoginPage) {
|
|
82
|
+
return { type: 'allow' };
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
type: 'redirect',
|
|
86
|
+
location: `/account-auth/login?callbackUrl=${encodeURIComponent(safeCallbackUrl)}&reason=stale_session`,
|
|
87
|
+
reason: 'stale_session',
|
|
88
|
+
clearCookies: true
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// PRIORITIZE 2FA: If session exists and 2FA is required but not complete, handle this before token-expired logic
|
|
92
|
+
if (sessionStatus.requires2FA && !sessionStatus.twoFactorComplete) {
|
|
93
|
+
console.log('[MIDDLEWARE-DECISION] 2FA required but not complete', {
|
|
94
|
+
pathname,
|
|
95
|
+
isLoginPage,
|
|
96
|
+
sessionExists: sessionStatus.exists,
|
|
97
|
+
sessionToken: sessionPointer.sessionToken?.substring(0, 8) + '...'
|
|
98
|
+
});
|
|
99
|
+
// Already on the 2FA page
|
|
100
|
+
if (pathname === '/account-auth/verify-code') {
|
|
101
|
+
console.log('[MIDDLEWARE-DECISION] Already on verify-code page, allowing');
|
|
102
|
+
return { type: 'allow' };
|
|
103
|
+
}
|
|
104
|
+
// If user is on the login page, send them to verify-code with the original callback
|
|
105
|
+
if (isLoginPage) {
|
|
106
|
+
const callbackUrl = searchParams.get('callbackUrl') || '/';
|
|
107
|
+
// CRITICAL FIX: Never use auth pages as callback URLs
|
|
108
|
+
const safeCallbackUrl = callbackUrl.startsWith('/account-auth/') ? '/' : callbackUrl;
|
|
109
|
+
console.log('[MIDDLEWARE-DECISION] On login page with 2FA incomplete, redirecting to verify-code', {
|
|
110
|
+
originalCallback: callbackUrl,
|
|
111
|
+
safeCallback: safeCallbackUrl,
|
|
112
|
+
originalUrl: pathname
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
type: 'redirect',
|
|
116
|
+
location: `/account-auth/verify-code?callbackUrl=${encodeURIComponent(safeCallbackUrl)}`,
|
|
117
|
+
reason: '2fa_required_login_redirect'
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// For protected routes, allow middleware to proceed (it may refresh tokens); pages will enforce 2FA
|
|
121
|
+
console.log('[MIDDLEWARE-DECISION] Protected route with incomplete 2FA, allowing middleware to handle');
|
|
122
|
+
return { type: 'allow' };
|
|
123
|
+
}
|
|
124
|
+
// Token expired - redirect to login
|
|
125
|
+
if (sessionPointer.expired) {
|
|
126
|
+
if (isLoginPage) {
|
|
127
|
+
return { type: 'allow' };
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
type: 'redirect',
|
|
131
|
+
location: `/account-auth/login?callbackUrl=${encodeURIComponent(safeCallbackUrl)}&error=SessionExpired`,
|
|
132
|
+
reason: 'token_expired'
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Authenticated root path should land on dashboards
|
|
136
|
+
if (pathname === '/') {
|
|
137
|
+
return {
|
|
138
|
+
type: 'redirect',
|
|
139
|
+
location: '/',
|
|
140
|
+
reason: 'authenticated_root_redirect'
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
// Valid session but 2FA required and not complete - more intelligent handling
|
|
144
|
+
if (sessionStatus.requires2FA && !sessionStatus.twoFactorComplete) {
|
|
145
|
+
if (pathname === '/account-auth/verify-code') {
|
|
146
|
+
return { type: 'allow' }; // Already on 2FA page
|
|
147
|
+
}
|
|
148
|
+
// For login page, redirect to 2FA with original callback
|
|
149
|
+
if (isLoginPage) {
|
|
150
|
+
const callbackUrl = searchParams.get('callbackUrl') || '/';
|
|
151
|
+
// CRITICAL FIX: Never use auth pages as callback URLs
|
|
152
|
+
const safeCallbackUrl = callbackUrl.startsWith('/account-auth/') ? '/' : callbackUrl;
|
|
153
|
+
return {
|
|
154
|
+
type: 'redirect',
|
|
155
|
+
location: `/account-auth/verify-code?callbackUrl=${encodeURIComponent(safeCallbackUrl)}`,
|
|
156
|
+
reason: '2fa_required'
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
// For protected routes:
|
|
160
|
+
// - If access token is expired and we have a valid refresh token, let middleware handle refresh first
|
|
161
|
+
// - Only redirect to verify-code if access token is still valid or refresh failed
|
|
162
|
+
// - Allow middleware to pass - it will either refresh successfully or handle redirect appropriately
|
|
163
|
+
return { type: 'allow' };
|
|
164
|
+
}
|
|
165
|
+
// Authenticated user on login page - redirect to dashboard or callback
|
|
166
|
+
if (isLoginPage) {
|
|
167
|
+
const callbackUrl = searchParams.get('callbackUrl') || '/';
|
|
168
|
+
// CRITICAL FIX: Never redirect back to login page (prevents infinite loop)
|
|
169
|
+
const safeCallbackUrl = callbackUrl.startsWith('/account-auth/') ? '/' : callbackUrl;
|
|
170
|
+
console.log('[MIDDLEWARE-DECISION] Authenticated user on login page, redirecting', {
|
|
171
|
+
originalCallback: callbackUrl,
|
|
172
|
+
safeCallback: safeCallbackUrl
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
type: 'redirect',
|
|
176
|
+
location: safeCallbackUrl,
|
|
177
|
+
reason: 'already_authenticated'
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// All checks passed - allow access
|
|
181
|
+
return { type: 'allow' };
|
|
182
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Better Auth Configuration
|
|
3
|
+
*
|
|
4
|
+
* Primary auth configuration. Replaces the former NextAuth auth-options.ts.
|
|
5
|
+
*
|
|
6
|
+
* Architecture: No database adapter — Better Auth runs in stateless mode
|
|
7
|
+
* with JWE cookie cache. User management stays on IDP, sessions on Redis.
|
|
8
|
+
*
|
|
9
|
+
* @see BETTER-AUTH-MIGRATION-SPEC.md
|
|
10
|
+
*/
|
|
11
|
+
import 'server-only';
|
|
12
|
+
import type { IDPClientConfig } from '../lib/idp-client-config';
|
|
13
|
+
/**
|
|
14
|
+
* Better Auth social provider config shape.
|
|
15
|
+
*/
|
|
16
|
+
export interface BetterAuthSocialProvider {
|
|
17
|
+
clientId: string;
|
|
18
|
+
clientSecret: string;
|
|
19
|
+
scope?: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build Better Auth social providers from IDP config.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildBetterAuthProviders(config: IDPClientConfig): Record<string, BetterAuthSocialProvider>;
|
|
25
|
+
/**
|
|
26
|
+
* Create Better Auth instance from IDP config.
|
|
27
|
+
*
|
|
28
|
+
* No database — runs in stateless mode with JWE cookie cache.
|
|
29
|
+
* Call after getIDPClientConfig() resolves.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createBetterAuthInstance(idpConfig: IDPClientConfig): import("better-auth").Auth<{
|
|
32
|
+
secret: string;
|
|
33
|
+
socialProviders: Record<string, BetterAuthSocialProvider>;
|
|
34
|
+
trustedOrigins: string[];
|
|
35
|
+
session: {
|
|
36
|
+
cookieCache: {
|
|
37
|
+
enabled: true;
|
|
38
|
+
maxAge: number;
|
|
39
|
+
refreshCache: true;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
plugins: [{
|
|
43
|
+
id: "next-cookies";
|
|
44
|
+
hooks: {
|
|
45
|
+
before: {
|
|
46
|
+
matcher(ctx: import("better-auth").HookEndpointContext): boolean;
|
|
47
|
+
handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>;
|
|
48
|
+
}[];
|
|
49
|
+
after: {
|
|
50
|
+
matcher(ctx: import("better-auth").HookEndpointContext): true;
|
|
51
|
+
handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>;
|
|
52
|
+
}[];
|
|
53
|
+
};
|
|
54
|
+
}];
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Better Auth is always enabled (NextAuth removed in 4.0).
|
|
58
|
+
*/
|
|
59
|
+
export declare function isBetterAuthEnabled(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Get flag-gated auth handler for Next.js route.
|
|
62
|
+
*
|
|
63
|
+
* When USE_BETTER_AUTH=true, returns Better Auth handlers.
|
|
64
|
+
* Otherwise returns null (auth disabled).
|
|
65
|
+
*
|
|
66
|
+
* Usage in host app route:
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { getBetterAuthHandler } from '@payez/next-mvp/auth/better-auth';
|
|
69
|
+
*
|
|
70
|
+
* export async function GET(req: Request) {
|
|
71
|
+
* const ba = await getBetterAuthHandler();
|
|
72
|
+
* if (ba) return ba.GET(req);
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function getBetterAuthHandler(): Promise<{
|
|
77
|
+
GET: (req: Request) => Promise<Response>;
|
|
78
|
+
POST: (req: Request) => Promise<Response>;
|
|
79
|
+
} | null>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Better Auth Configuration
|
|
4
|
+
*
|
|
5
|
+
* Primary auth configuration. Replaces the former NextAuth auth-options.ts.
|
|
6
|
+
*
|
|
7
|
+
* Architecture: No database adapter — Better Auth runs in stateless mode
|
|
8
|
+
* with JWE cookie cache. User management stays on IDP, sessions on Redis.
|
|
9
|
+
*
|
|
10
|
+
* @see BETTER-AUTH-MIGRATION-SPEC.md
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.buildBetterAuthProviders = buildBetterAuthProviders;
|
|
14
|
+
exports.createBetterAuthInstance = createBetterAuthInstance;
|
|
15
|
+
exports.isBetterAuthEnabled = isBetterAuthEnabled;
|
|
16
|
+
exports.getBetterAuthHandler = getBetterAuthHandler;
|
|
17
|
+
require("server-only");
|
|
18
|
+
const better_auth_1 = require("better-auth");
|
|
19
|
+
const next_js_1 = require("better-auth/next-js");
|
|
20
|
+
const next_js_2 = require("better-auth/next-js");
|
|
21
|
+
const idp_client_config_1 = require("../lib/idp-client-config");
|
|
22
|
+
/**
|
|
23
|
+
* Build Better Auth social providers from IDP config.
|
|
24
|
+
*/
|
|
25
|
+
function buildBetterAuthProviders(config) {
|
|
26
|
+
const providers = {};
|
|
27
|
+
for (const oauth of config.oauthProviders || []) {
|
|
28
|
+
if (!oauth.enabled)
|
|
29
|
+
continue;
|
|
30
|
+
const name = oauth.provider.toLowerCase();
|
|
31
|
+
providers[name] = {
|
|
32
|
+
clientId: oauth.clientId,
|
|
33
|
+
clientSecret: oauth.clientSecret,
|
|
34
|
+
scope: oauth.scopes?.split(' '),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return providers;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create Better Auth instance from IDP config.
|
|
41
|
+
*
|
|
42
|
+
* No database — runs in stateless mode with JWE cookie cache.
|
|
43
|
+
* Call after getIDPClientConfig() resolves.
|
|
44
|
+
*/
|
|
45
|
+
function createBetterAuthInstance(idpConfig) {
|
|
46
|
+
return (0, better_auth_1.betterAuth)({
|
|
47
|
+
secret: idpConfig.nextAuthSecret,
|
|
48
|
+
socialProviders: buildBetterAuthProviders(idpConfig),
|
|
49
|
+
// Trust the app's own origin + any configured base URL
|
|
50
|
+
trustedOrigins: [
|
|
51
|
+
...(idpConfig.baseClientUrl ? [idpConfig.baseClientUrl] : []),
|
|
52
|
+
...(process.env.BETTER_AUTH_URL ? [process.env.BETTER_AUTH_URL] : []),
|
|
53
|
+
'http://localhost:3000',
|
|
54
|
+
'http://localhost:3400',
|
|
55
|
+
'http://localhost:3600',
|
|
56
|
+
],
|
|
57
|
+
// No database — stateless mode. Better Auth defaults to JWE cookie cache.
|
|
58
|
+
// Session cookie cache with refreshCache for DB-less setup.
|
|
59
|
+
session: {
|
|
60
|
+
cookieCache: {
|
|
61
|
+
enabled: true,
|
|
62
|
+
maxAge: 300,
|
|
63
|
+
refreshCache: true,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
plugins: [
|
|
67
|
+
(0, next_js_1.nextCookies)(),
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Better Auth is always enabled (NextAuth removed in 4.0).
|
|
73
|
+
*/
|
|
74
|
+
function isBetterAuthEnabled() {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get Better Auth Next.js route handlers (GET, POST).
|
|
79
|
+
* Initializes Better Auth from IDP config on first call, caches the instance.
|
|
80
|
+
*/
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
+
let cachedInstance = null;
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
let initPromise = null;
|
|
85
|
+
async function getBetterAuthInstance() {
|
|
86
|
+
if (cachedInstance)
|
|
87
|
+
return cachedInstance;
|
|
88
|
+
if (!initPromise) {
|
|
89
|
+
initPromise = (0, idp_client_config_1.getIDPClientConfig)().then(config => {
|
|
90
|
+
const instance = createBetterAuthInstance(config);
|
|
91
|
+
cachedInstance = instance;
|
|
92
|
+
console.log('[BETTER_AUTH] Instance created for', config.clientSlug || config.clientId);
|
|
93
|
+
return instance;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return initPromise;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get flag-gated auth handler for Next.js route.
|
|
100
|
+
*
|
|
101
|
+
* When USE_BETTER_AUTH=true, returns Better Auth handlers.
|
|
102
|
+
* Otherwise returns null (auth disabled).
|
|
103
|
+
*
|
|
104
|
+
* Usage in host app route:
|
|
105
|
+
* ```ts
|
|
106
|
+
* import { getBetterAuthHandler } from '@payez/next-mvp/auth/better-auth';
|
|
107
|
+
*
|
|
108
|
+
* export async function GET(req: Request) {
|
|
109
|
+
* const ba = await getBetterAuthHandler();
|
|
110
|
+
* if (ba) return ba.GET(req);
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
async function getBetterAuthHandler() {
|
|
115
|
+
if (!isBetterAuthEnabled())
|
|
116
|
+
return null;
|
|
117
|
+
const auth = await getBetterAuthInstance();
|
|
118
|
+
return (0, next_js_2.toNextJsHandler)(auth);
|
|
119
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advanced Route Configuration for `@payez/next-mvp`
|
|
3
|
+
*
|
|
4
|
+
* This module provides a robust, pattern-based mechanism for defining
|
|
5
|
+
* unauthenticated (public) routes, including wildcard support.
|
|
6
|
+
* It is designed to be easily configurable by host applications.
|
|
7
|
+
*/
|
|
8
|
+
import { TwoFactorRequirements } from '../middleware/twofa-presets';
|
|
9
|
+
export interface UnauthenticatedRouteConfig {
|
|
10
|
+
/** The route pattern (supports wildcards with *) */
|
|
11
|
+
pattern: string;
|
|
12
|
+
/** Description of what this route is for */
|
|
13
|
+
description: string;
|
|
14
|
+
/** Whether this route should be accessible during circuit breaker open state */
|
|
15
|
+
allowDuringCircuitBreakerOpen?: boolean;
|
|
16
|
+
/** Whether this route requires rate limiting even when unauthenticated */
|
|
17
|
+
requiresRateLimit?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Protected route configuration with 2FA requirements
|
|
21
|
+
*/
|
|
22
|
+
export interface ProtectedRouteConfig {
|
|
23
|
+
/** The route pattern (supports wildcards with *) */
|
|
24
|
+
pattern: string;
|
|
25
|
+
/** Description of what this route is for */
|
|
26
|
+
description?: string;
|
|
27
|
+
/** 2FA requirements for this route (default: requires 2FA if site requires it) */
|
|
28
|
+
twoFactorRequirements: TwoFactorRequirements;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Configures additional public routes for the application.
|
|
32
|
+
* This function should be called once during application initialization.
|
|
33
|
+
* @param appRoutes An array of route patterns or UnauthenticatedRouteConfig objects.
|
|
34
|
+
*/
|
|
35
|
+
export declare function configurePublicRoutes(appRoutes?: (string | UnauthenticatedRouteConfig)[]): void;
|
|
36
|
+
/**
|
|
37
|
+
* Configures routes that require authentication but bypass 2FA requirements.
|
|
38
|
+
* Essential for 2FA onboarding flows where user is authenticated but hasn't completed 2FA yet.
|
|
39
|
+
* @param routes An array of route patterns or ProtectedRouteConfig objects.
|
|
40
|
+
*/
|
|
41
|
+
export declare function configure2FABypassRoutes(routes?: (string | ProtectedRouteConfig)[]): void;
|
|
42
|
+
/**
|
|
43
|
+
* Checks if a route should bypass 2FA requirements (but still requires auth).
|
|
44
|
+
* @param pathname The URL pathname to check.
|
|
45
|
+
* @returns The ProtectedRouteConfig if found, otherwise undefined.
|
|
46
|
+
*/
|
|
47
|
+
export declare function get2FABypassConfig(pathname: string): ProtectedRouteConfig | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Checks if a route should bypass 2FA requirements.
|
|
50
|
+
* @param pathname The URL pathname to check.
|
|
51
|
+
* @returns true if 2FA should be bypassed for this route.
|
|
52
|
+
*/
|
|
53
|
+
export declare function should2FABypass(pathname: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Checks if a given pathname matches any of the configured unauthenticated routes.
|
|
56
|
+
* Supports wildcard matching (e.g., '/api/*').
|
|
57
|
+
* @param pathname The URL pathname to check.
|
|
58
|
+
* @returns `true` if the route is unauthenticated, `false` otherwise.
|
|
59
|
+
*/
|
|
60
|
+
export declare function isUnauthenticatedRoute(pathname: string): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Retrieves the configuration for a specific route.
|
|
63
|
+
* @param pathname The URL pathname to get the configuration for.
|
|
64
|
+
* @returns The `UnauthenticatedRouteConfig` object if found, otherwise `undefined`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function getRouteConfig(pathname: string): UnauthenticatedRouteConfig | undefined;
|