@payez/next-mvp 4.8.1 → 4.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/POST-INSTALL.md +408 -408
- package/README.md +859 -859
- package/dist/components/account/MobileNavDrawer.js +18 -18
- package/dist/components/account/UserAvatarMenu.js +1 -1
- package/dist/components/admin/AlertSettingsTab.js +40 -40
- package/dist/components/admin/LoggingSettingsTab.js +28 -28
- package/dist/lib/session-store.js +21 -21
- package/dist/lib/startup-init.js +19 -19
- package/dist/pages/login/page.js +28 -28
- package/dist/pages/settings/EnhancedSettingsPage.js +17 -17
- package/dist/vibe/sessions.js +28 -3
- package/package.json +2 -2
- package/scripts/check-publish-eol.mjs +33 -15
- package/src/api/auth-handler.ts +550 -550
- package/src/api/index.ts +17 -17
- package/src/api-handlers/account/change-password.ts +170 -170
- package/src/api-handlers/account/masked-info.ts +46 -46
- package/src/api-handlers/account/profile.ts +99 -99
- package/src/api-handlers/account/recovery/forward.ts +117 -117
- package/src/api-handlers/account/recovery/initiate.ts +59 -59
- package/src/api-handlers/account/recovery/send-code.ts +21 -21
- package/src/api-handlers/account/recovery/verify-code.ts +20 -20
- package/src/api-handlers/account/reset-password.ts +87 -87
- package/src/api-handlers/account/send-code.ts +70 -70
- package/src/api-handlers/account/update-phone.ts +84 -84
- package/src/api-handlers/account/validate-password.ts +139 -139
- package/src/api-handlers/account/verify-email.ts +134 -134
- package/src/api-handlers/account/verify-sms.ts +134 -134
- package/src/api-handlers/admin/analytics.ts +452 -452
- package/src/api-handlers/admin/audit.ts +232 -232
- package/src/api-handlers/admin/index.ts +63 -63
- package/src/api-handlers/admin/redis-sessions.ts +259 -259
- package/src/api-handlers/admin/sessions.ts +327 -327
- package/src/api-handlers/admin/site-logs.ts +388 -388
- package/src/api-handlers/admin/stats.ts +260 -260
- package/src/api-handlers/admin/users.ts +251 -251
- package/src/api-handlers/admin/vibe-data.ts +333 -333
- package/src/api-handlers/anon/preferences.ts +123 -123
- package/src/api-handlers/auth/credential-login-email-code.ts +92 -92
- package/src/api-handlers/auth/credential-login.ts +948 -948
- package/src/api-handlers/auth/jwks.ts +31 -31
- package/src/api-handlers/auth/login.ts +252 -252
- package/src/api-handlers/auth/passkey-signin.ts +116 -116
- package/src/api-handlers/auth/refresh.ts +829 -829
- package/src/api-handlers/auth/signout.ts +201 -201
- package/src/api-handlers/auth/status.ts +23 -23
- package/src/api-handlers/auth/update-session.ts +144 -144
- package/src/api-handlers/auth/validate.ts +45 -45
- package/src/api-handlers/auth/verify-code.ts +116 -116
- package/src/api-handlers/mfa/backup-code-verify.ts +170 -170
- package/src/api-handlers/mfa/backup-codes.ts +42 -42
- package/src/api-handlers/mfa/methods.ts +47 -47
- package/src/api-handlers/mfa/totp-confirm.ts +43 -43
- package/src/api-handlers/mfa/totp-enroll.ts +43 -43
- package/src/api-handlers/mfa/totp-verify.ts +172 -172
- package/src/api-handlers/oauth/resume.ts +182 -182
- package/src/api-handlers/onboarding/send-email-code.ts +18 -18
- package/src/api-handlers/onboarding/set-password.ts +21 -21
- package/src/api-handlers/onboarding/verify-code.ts +20 -20
- package/src/api-handlers/onboarding/verify-welcome-email.ts +17 -17
- package/src/api-handlers/passkeys/list.ts +32 -32
- package/src/api-handlers/passkeys/manage.ts +55 -55
- package/src/api-handlers/passkeys/register-options.ts +43 -43
- package/src/api-handlers/passkeys/register-verify.ts +42 -42
- package/src/api-handlers/session/refresh-viability.ts +56 -56
- package/src/api-handlers/session/viability.ts +238 -238
- package/src/api-handlers/test/force-expire.ts +167 -167
- package/src/auth/auth-decision.ts +292 -292
- package/src/auth/better-auth.ts +1688 -1688
- package/src/auth/idp-oauth.ts +310 -310
- package/src/auth/password-reset-bridge.ts +98 -98
- package/src/auth/revocation-fields.ts +16 -16
- package/src/auth/route-config.ts +236 -236
- package/src/auth/safe-callback.ts +199 -199
- package/src/auth/session-cookie-clear.ts +30 -30
- package/src/auth/session-reset-link.ts +159 -159
- package/src/auth/session-response-sanitizer.ts +151 -151
- package/src/auth/types/auth-types.ts +555 -555
- package/src/auth/types/index.ts +7 -7
- package/src/auth/unauthenticated-routes.ts +2 -2
- package/src/auth/utils/idp-client.ts +364 -364
- package/src/auth/utils/index.ts +6 -6
- package/src/auth/utils/token-utils.ts +243 -243
- package/src/client/AuthContext.tsx +192 -192
- package/src/client/better-auth-client.ts +70 -70
- package/src/client/fetch-with-auth.ts +47 -47
- package/src/client/fetchWithSession.ts +21 -21
- package/src/client/index.ts +13 -13
- package/src/client/useAnonSession.ts +131 -131
- package/src/components/SessionSync.tsx +138 -138
- package/src/components/SignalRHealthCheck.tsx +131 -131
- package/src/components/account/MobileNavDrawer.tsx +305 -305
- package/src/components/account/UserAvatarMenu.tsx +277 -277
- package/src/components/account/index.ts +13 -13
- package/src/components/admin/AlertSettingsTab.tsx +728 -728
- package/src/components/admin/AnalyticsTab.tsx +703 -703
- package/src/components/admin/DataBrowserTab.tsx +508 -508
- package/src/components/admin/LoggingSettingsTab.tsx +665 -665
- package/src/components/admin/SessionsTab.tsx +421 -421
- package/src/components/admin/StatsTab.tsx +379 -379
- package/src/components/admin/VibeAdminContext.tsx +87 -87
- package/src/components/admin/VibeAdminLayout.tsx +187 -187
- package/src/components/admin/index.ts +59 -59
- package/src/components/auth/CredentialSignInForm.tsx +240 -240
- package/src/components/auth/FederatedAuthSection.tsx +129 -129
- package/src/components/auth/ModeAwareLoginPage.tsx +146 -146
- package/src/components/auth/ModeAwareSignupPage.tsx +200 -200
- package/src/components/auth/PasswordResetBridge.tsx +30 -30
- package/src/components/auth/TraditionalAuthSection.tsx +103 -103
- package/src/components/recovery/CompleteStep.tsx +36 -36
- package/src/components/recovery/InitiateRecoveryStep.tsx +68 -68
- package/src/components/recovery/RequestedStep.tsx +30 -30
- package/src/components/recovery/SelectMethodStep.tsx +73 -73
- package/src/components/recovery/SetPasswordStep.tsx +118 -118
- package/src/components/recovery/VerifyCodeStep.tsx +90 -90
- package/src/components/reserved/ReservedRecoveryWarning.tsx +160 -160
- package/src/components/reserved/ReservedStatusBox.tsx +118 -118
- package/src/components/ui/BetaBadge.tsx +58 -58
- package/src/components/ui/Footer.tsx +93 -93
- package/src/config/env.ts +55 -55
- package/src/config/logger.ts +62 -62
- package/src/config/logging-config.ts +82 -82
- package/src/config/unauthenticated-routes.ts +19 -19
- package/src/config/vibe-log-transport.ts +264 -264
- package/src/edge/internal-api-url.ts +65 -65
- package/src/edge/middleware.ts +42 -42
- package/src/hooks/useAuth.ts +117 -117
- package/src/hooks/useAuthSettings.ts +109 -109
- package/src/hooks/useAvailableProviders.ts +143 -143
- package/src/hooks/usePasswordValidation.ts +127 -127
- package/src/hooks/useProfile.ts +82 -82
- package/src/hooks/usePublicAuthSettings.ts +171 -171
- package/src/hooks/useSessionExpiration.ts +101 -101
- package/src/hooks/useViabilitySession.ts +337 -337
- package/src/index.ts +64 -64
- package/src/lib/anon-session.ts +213 -213
- package/src/lib/api-handler.ts +643 -643
- package/src/lib/app-slug.ts +228 -228
- package/src/lib/authorize-resume.ts +172 -172
- package/src/lib/bearer-fetch.ts +31 -31
- package/src/lib/client-key.ts +88 -88
- package/src/lib/code-step-copy.ts +83 -83
- package/src/lib/credential-sign-in-client.ts +101 -101
- package/src/lib/demo-mode.ts +18 -18
- package/src/lib/device-id.ts +67 -67
- package/src/lib/ensure-fresh-access-token.ts +509 -509
- package/src/lib/geolocation.ts +265 -265
- package/src/lib/idp-client-config.ts +1005 -1005
- package/src/lib/idp-fetch.ts +169 -169
- package/src/lib/idp-url-guard.ts +37 -37
- package/src/lib/internal-api.ts +171 -171
- package/src/lib/jwt-decode-client.ts +45 -45
- package/src/lib/jwt-decode.ts +82 -82
- package/src/lib/lock-window.ts +49 -49
- package/src/lib/login-error-message.ts +41 -41
- package/src/lib/never-in-response.ts +64 -64
- package/src/lib/nextauth-secret.ts +168 -168
- package/src/lib/onboarding-proxy.ts +57 -57
- package/src/lib/password-rules.ts +50 -50
- package/src/lib/rate-limit-service.ts +9 -9
- package/src/lib/redis.ts +105 -105
- package/src/lib/refresh-token-validator.ts +64 -64
- package/src/lib/roles.ts +177 -177
- package/src/lib/safe-error-response.ts +149 -149
- package/src/lib/secret-validation.ts +8 -8
- package/src/lib/session-cookie-shape.ts +185 -185
- package/src/lib/session-store.ts +1092 -1092
- package/src/lib/session.ts +34 -34
- package/src/lib/single-flight.ts +64 -64
- package/src/lib/site-logger.ts +245 -245
- package/src/lib/standardized-client-api.ts +901 -901
- package/src/lib/startup-init.ts +276 -276
- package/src/lib/test-aware-get-token.ts +41 -41
- package/src/lib/token-expiry.ts +40 -40
- package/src/lib/token-lifecycle.ts +546 -546
- package/src/lib/token-log-id.ts +69 -69
- package/src/lib/twofa-rejection.ts +91 -91
- package/src/lib/types/api-responses.ts +336 -336
- package/src/lib/user-agent-parser.ts +252 -252
- package/src/logging/api/admin-analytics.ts +51 -51
- package/src/logging/api/audit-log.ts +53 -53
- package/src/logging/components/AdminAnalyticsLayout.tsx +49 -49
- package/src/logging/components/AuditLogViewer.tsx +125 -125
- package/src/logging/components/ErrorMetricsCard.tsx +98 -98
- package/src/logging/components/HealthMetricsCard.tsx +70 -70
- package/src/logging/hooks/useAdminAnalytics.ts +22 -22
- package/src/logging/hooks/useAuditLog.ts +24 -24
- package/src/logging/hooks/useErrorMetrics.ts +40 -40
- package/src/logging/hooks/useHealthMetrics.ts +44 -44
- package/src/logging/index.ts +18 -18
- package/src/logging/types/analytics.ts +81 -81
- package/src/logging/types/audit.ts +31 -31
- package/src/logging/types/index.ts +3 -3
- package/src/middleware/create-middleware.ts +1141 -1141
- package/src/middleware/rbac-check.ts +279 -279
- package/src/middleware/twofa-presets.ts +224 -224
- package/src/models/DecodedAccessToken.ts +16 -16
- package/src/models/SessionModel.ts +331 -331
- package/src/pages/admin-login/page.tsx +111 -111
- package/src/pages/admin-page-permissions/PagePermissionsAdminPage.tsx +527 -527
- package/src/pages/admin-page-permissions/index.ts +7 -7
- package/src/pages/admin-roles/RolesAdminPage.tsx +533 -533
- package/src/pages/admin-roles/index.ts +9 -9
- package/src/pages/admin-roles/modals.tsx +469 -469
- package/src/pages/client-admin/ClientSiteAdminPage.tsx +382 -382
- package/src/pages/client-admin/index.ts +33 -33
- package/src/pages/coming-soon/page.tsx +83 -83
- package/src/pages/login/page.tsx +338 -338
- package/src/pages/onboarding/index.ts +11 -11
- package/src/pages/onboarding/page.tsx +212 -212
- package/src/pages/profile/EnhancedProfilePage.tsx +514 -514
- package/src/pages/profile/index.ts +9 -9
- package/src/pages/profile/page.tsx +166 -166
- package/src/pages/recovery/page.tsx +267 -267
- package/src/pages/roles/MyRolesPage.tsx +211 -211
- package/src/pages/roles/components.tsx +294 -294
- package/src/pages/roles/index.ts +17 -17
- package/src/pages/security/EnhancedSecurityPage.tsx +660 -660
- package/src/pages/security/index.ts +12 -12
- package/src/pages/security/page.tsx +507 -507
- package/src/pages/service-unavailable/page.tsx +63 -63
- package/src/pages/settings/EnhancedSettingsPage.tsx +642 -642
- package/src/pages/settings/index.ts +9 -9
- package/src/pages/settings/page.tsx +47 -47
- package/src/pages/showcase/ShowcasePage.tsx +532 -532
- package/src/pages/showcase/index.ts +13 -13
- package/src/pages/test-env/EmergencyLogoutPage.tsx +192 -192
- package/src/pages/test-env/JwtInspectPage.tsx +449 -449
- package/src/pages/test-env/RefreshTokenPage.tsx +178 -178
- package/src/pages/test-env/TestEnvPage.tsx +130 -130
- package/src/pages/test-env/guarded.tsx +81 -81
- package/src/pages/test-env/index.ts +77 -77
- package/src/pages/test-env/redact-credentials.ts +96 -96
- package/src/pages/verify-code/page.tsx +746 -746
- package/src/routes/account/index.ts +31 -31
- package/src/routes/account/masked-info.ts +36 -36
- package/src/routes/account/send-code.ts +39 -39
- package/src/routes/account/update-phone.ts +13 -13
- package/src/routes/account/verify-email.ts +40 -40
- package/src/routes/account/verify-sms.ts +40 -40
- package/src/routes/auth/credential-login-email-code.ts +6 -6
- package/src/routes/auth/credential-login.ts +6 -6
- package/src/routes/auth/index.ts +22 -22
- package/src/routes/auth/logout.ts +111 -111
- package/src/routes/auth/nextauth.ts +45 -45
- package/src/routes/auth/passkey-signin.ts +13 -13
- package/src/routes/auth/refresh.ts +77 -77
- package/src/routes/auth/session-reset.ts +37 -37
- package/src/routes/auth/session.ts +261 -261
- package/src/routes/auth/settings.ts +181 -181
- package/src/routes/auth/viability.ts +519 -519
- package/src/routes/index.ts +17 -17
- package/src/routes/mfa/backup-code-verify.ts +1 -1
- package/src/routes/mfa/backup-codes.ts +10 -10
- package/src/routes/mfa/methods.ts +22 -22
- package/src/routes/mfa/totp-confirm.ts +10 -10
- package/src/routes/mfa/totp-enroll.ts +10 -10
- package/src/routes/mfa/totp-verify.ts +14 -14
- package/src/routes/onboarding/index.ts +15 -15
- package/src/routes/onboarding/send-email-code.ts +2 -2
- package/src/routes/onboarding/set-password.ts +2 -2
- package/src/routes/onboarding/verify-code.ts +2 -2
- package/src/routes/onboarding/verify-welcome-email.ts +2 -2
- package/src/routes/passkeys/list.ts +10 -10
- package/src/routes/passkeys/manage.ts +23 -23
- package/src/routes/passkeys/register-options.ts +10 -10
- package/src/routes/passkeys/register-verify.ts +10 -10
- package/src/routes/session/index.ts +7 -7
- package/src/routes/session/refresh-viability.ts +17 -17
- package/src/server/auth-guard.ts +203 -203
- package/src/server/auth.ts +486 -486
- package/src/server/decode-session.ts +309 -309
- package/src/server/slim-middleware.ts +117 -117
- package/src/server/verified-session-token.ts +103 -103
- package/src/server/with-auth.ts +93 -93
- package/src/services/signalrActivityService.ts +258 -258
- package/src/stores/authStore.ts +1900 -1900
- package/src/templates/instrumentation.ts +60 -60
- package/src/theme/ThemeProvider.tsx +39 -39
- package/src/theme/default.ts +33 -33
- package/src/theme/index.ts +31 -31
- package/src/theme/types.ts +69 -69
- package/src/theme/useTheme.ts +57 -57
- package/src/theme/utils.ts +40 -40
- package/src/types/api.ts +12 -12
- package/src/types/auth.d.ts +23 -23
- package/src/types/auth.ts +48 -48
- package/src/types/logging.ts +11 -11
- package/src/types/recovery.ts +54 -54
- package/src/utils/api.ts +401 -401
- package/src/utils/circuitBreaker.ts +40 -40
- package/src/utils/error-message.ts +108 -108
- package/src/utils/layout/reservedSpace.ts +124 -124
- package/src/utils/logout.ts +30 -30
- package/src/vibe/client.ts +877 -877
- package/src/vibe/enterprise-auth.ts +208 -208
- package/src/vibe/errors.ts +209 -209
- package/src/vibe/generic.ts +339 -339
- package/src/vibe/hooks/index.ts +367 -367
- package/src/vibe/index.ts +133 -133
- package/src/vibe/sessions.ts +925 -899
- package/src/vibe/types.ts +577 -577
package/src/edge/middleware.ts
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Edge Runtime Compatible Exports
|
|
3
|
-
*
|
|
4
|
-
* This module exports only Edge Runtime compatible code for use in Next.js middleware.
|
|
5
|
-
* Client-side utilities that depend on browser APIs or server-only code are excluded.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// Authentication middleware and configuration (Edge Runtime compatible)
|
|
9
|
-
export { makeAuthDecision } from '../auth/auth-decision';
|
|
10
|
-
export {
|
|
11
|
-
isUnauthenticatedRoute,
|
|
12
|
-
configurePublicRoutes,
|
|
13
|
-
getRouteConfig,
|
|
14
|
-
configure2FABypassRoutes,
|
|
15
|
-
should2FABypass,
|
|
16
|
-
get2FABypassConfig
|
|
17
|
-
} from '../auth/route-config';
|
|
18
|
-
export type { UnauthenticatedRouteConfig, ProtectedRouteConfig } from '../auth/route-config';
|
|
19
|
-
export { createMvpMiddleware, isPrefetchRequest } from '../middleware/create-middleware';
|
|
20
|
-
export type {
|
|
21
|
-
MvpMiddlewareOptions,
|
|
22
|
-
CircuitBreakerProvider,
|
|
23
|
-
MiddlewareLogger,
|
|
24
|
-
AuthContext,
|
|
25
|
-
AuthAction,
|
|
26
|
-
SessionPointer,
|
|
27
|
-
SessionStatus
|
|
28
|
-
} from '../middleware/create-middleware';
|
|
29
|
-
|
|
30
|
-
// Two-Factor Authentication Presets (Edge Runtime compatible)
|
|
31
|
-
export {
|
|
32
|
-
TwoFactorPresets,
|
|
33
|
-
AMRValues,
|
|
34
|
-
ACRLevels,
|
|
35
|
-
validateAMR,
|
|
36
|
-
validateACR,
|
|
37
|
-
checkTwoFactorRequirements
|
|
38
|
-
} from '../middleware/twofa-presets';
|
|
39
|
-
export type { TwoFactorRequirements, RouteConfig } from '../middleware/twofa-presets';
|
|
40
|
-
|
|
41
|
-
// Internal API URL utilities for Edge Runtime
|
|
42
|
-
export { getInternalApiUrl } from './internal-api-url';
|
|
1
|
+
/**
|
|
2
|
+
* Edge Runtime Compatible Exports
|
|
3
|
+
*
|
|
4
|
+
* This module exports only Edge Runtime compatible code for use in Next.js middleware.
|
|
5
|
+
* Client-side utilities that depend on browser APIs or server-only code are excluded.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Authentication middleware and configuration (Edge Runtime compatible)
|
|
9
|
+
export { makeAuthDecision } from '../auth/auth-decision';
|
|
10
|
+
export {
|
|
11
|
+
isUnauthenticatedRoute,
|
|
12
|
+
configurePublicRoutes,
|
|
13
|
+
getRouteConfig,
|
|
14
|
+
configure2FABypassRoutes,
|
|
15
|
+
should2FABypass,
|
|
16
|
+
get2FABypassConfig
|
|
17
|
+
} from '../auth/route-config';
|
|
18
|
+
export type { UnauthenticatedRouteConfig, ProtectedRouteConfig } from '../auth/route-config';
|
|
19
|
+
export { createMvpMiddleware, isPrefetchRequest } from '../middleware/create-middleware';
|
|
20
|
+
export type {
|
|
21
|
+
MvpMiddlewareOptions,
|
|
22
|
+
CircuitBreakerProvider,
|
|
23
|
+
MiddlewareLogger,
|
|
24
|
+
AuthContext,
|
|
25
|
+
AuthAction,
|
|
26
|
+
SessionPointer,
|
|
27
|
+
SessionStatus
|
|
28
|
+
} from '../middleware/create-middleware';
|
|
29
|
+
|
|
30
|
+
// Two-Factor Authentication Presets (Edge Runtime compatible)
|
|
31
|
+
export {
|
|
32
|
+
TwoFactorPresets,
|
|
33
|
+
AMRValues,
|
|
34
|
+
ACRLevels,
|
|
35
|
+
validateAMR,
|
|
36
|
+
validateACR,
|
|
37
|
+
checkTwoFactorRequirements
|
|
38
|
+
} from '../middleware/twofa-presets';
|
|
39
|
+
export type { TwoFactorRequirements, RouteConfig } from '../middleware/twofa-presets';
|
|
40
|
+
|
|
41
|
+
// Internal API URL utilities for Edge Runtime
|
|
42
|
+
export { getInternalApiUrl } from './internal-api-url';
|
package/src/hooks/useAuth.ts
CHANGED
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ⚠️ WARNING: This hook cannot be used directly from the @payez/next-mvp package!
|
|
5
|
-
*
|
|
6
|
-
* @deprecated Import this hook from your local app instead
|
|
7
|
-
*
|
|
8
|
-
* **Why?** React Context (SessionProvider) cannot cross package boundaries in file:// linked packages.
|
|
9
|
-
*
|
|
10
|
-
* **Solution:** Create a local version in your app (e.g., src/hooks/useAuth.ts) that imports standardizedApi:
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* // src/hooks/useAuth.ts (YOUR APP)
|
|
15
|
-
* 'use client';
|
|
16
|
-
* import { authClient } from '@payez/next-mvp/client/better-auth-client';
|
|
17
|
-
* import { standardizedApi } from '@payez/next-mvp/lib/standardized-client-api';
|
|
18
|
-
*
|
|
19
|
-
* export function useAuth() {
|
|
20
|
-
* const { data: session } = useSession(); // Works in your app context
|
|
21
|
-
* // ... implementation
|
|
22
|
-
* }
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* @see {@link https://github.com/payez/next-mvp/blob/main/docs/centralized-auth-api-pattern.md#why-local-hooks-for-auth Complete documentation}
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
import { authClient } from '../client/better-auth-client';
|
|
29
|
-
import { useCallback } from 'react';
|
|
30
|
-
import { useRouter } from 'next/navigation';
|
|
31
|
-
import { standardizedApi, ApiResult } from '../lib/standardized-client-api';
|
|
32
|
-
|
|
33
|
-
// Custom session type matching NextAuth structure
|
|
34
|
-
export interface CustomSession {
|
|
35
|
-
user: {
|
|
36
|
-
id: string;
|
|
37
|
-
email: string;
|
|
38
|
-
roles?: string[];
|
|
39
|
-
twoFactorMethod?: string;
|
|
40
|
-
twoFactorSessionVerified?: boolean;
|
|
41
|
-
requiresTwoFactor?: boolean;
|
|
42
|
-
};
|
|
43
|
-
accessToken?: string;
|
|
44
|
-
refreshToken?: string;
|
|
45
|
-
expires: string;
|
|
46
|
-
error?: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface UseAuthResult {
|
|
50
|
-
session: CustomSession | null;
|
|
51
|
-
status: 'loading' | 'authenticated' | 'unauthenticated';
|
|
52
|
-
isLoading: boolean;
|
|
53
|
-
isAuthenticated: boolean;
|
|
54
|
-
// API helper that automatically includes the auth token
|
|
55
|
-
apiCall: <T>(url: string, method?: 'GET' | 'POST' | 'PUT' | 'DELETE', data?: any) => Promise<ApiResult<T>>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function useAuth(): UseAuthResult {
|
|
59
|
-
const { data: sessionData, isPending } = authClient.useSession();
|
|
60
|
-
const session = sessionData;
|
|
61
|
-
const status = isPending ? 'loading' : session ? 'authenticated' : 'unauthenticated';
|
|
62
|
-
const router = useRouter();
|
|
63
|
-
|
|
64
|
-
const isLoading = status === 'loading';
|
|
65
|
-
const isAuthenticated = status === 'authenticated' && !!(session as any)?.accessToken;
|
|
66
|
-
|
|
67
|
-
// Handle sign out with redirect
|
|
68
|
-
const handleSignOut = useCallback(async () => {
|
|
69
|
-
await authClient.signOut();
|
|
70
|
-
router.push('/account-auth/login?error=SessionExpired');
|
|
71
|
-
}, [router]);
|
|
72
|
-
|
|
73
|
-
// API helper that automatically includes the auth token and uses standardized API
|
|
74
|
-
const apiCall = useCallback(
|
|
75
|
-
async <T>(url: string, method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'GET', data?: any): Promise<ApiResult<T>> => {
|
|
76
|
-
if (!(session as any)?.accessToken) {
|
|
77
|
-
console.error('[useAuth] No access token available');
|
|
78
|
-
throw new Error('Not authenticated');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
// Use standardized API which handles token refresh and validates response format
|
|
83
|
-
switch (method) {
|
|
84
|
-
case 'GET':
|
|
85
|
-
return await standardizedApi.get<T>(url, (session as any).accessToken!);
|
|
86
|
-
case 'POST':
|
|
87
|
-
return await standardizedApi.post<T>(url, data, (session as any).accessToken!);
|
|
88
|
-
case 'PUT':
|
|
89
|
-
return await standardizedApi.put<T>(url, data);
|
|
90
|
-
case 'DELETE':
|
|
91
|
-
return await standardizedApi.delete<T>(url);
|
|
92
|
-
default:
|
|
93
|
-
throw new Error(`Unsupported method: ${method}`);
|
|
94
|
-
}
|
|
95
|
-
} catch (error) {
|
|
96
|
-
console.error('[useAuth] API call failed:', error);
|
|
97
|
-
|
|
98
|
-
// standardizedApi handles token refresh internally, but if we still get auth errors, sign out
|
|
99
|
-
if (error instanceof Error && error.message.includes('Authentication failed')) {
|
|
100
|
-
console.warn('[useAuth] Authentication failed, signing out...');
|
|
101
|
-
await handleSignOut();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
throw error;
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
[(session as any)?.accessToken, handleSignOut]
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
session: session as CustomSession | null,
|
|
112
|
-
status,
|
|
113
|
-
isLoading,
|
|
114
|
-
isAuthenticated,
|
|
115
|
-
apiCall
|
|
116
|
-
};
|
|
117
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ⚠️ WARNING: This hook cannot be used directly from the @payez/next-mvp package!
|
|
5
|
+
*
|
|
6
|
+
* @deprecated Import this hook from your local app instead
|
|
7
|
+
*
|
|
8
|
+
* **Why?** React Context (SessionProvider) cannot cross package boundaries in file:// linked packages.
|
|
9
|
+
*
|
|
10
|
+
* **Solution:** Create a local version in your app (e.g., src/hooks/useAuth.ts) that imports standardizedApi:
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // src/hooks/useAuth.ts (YOUR APP)
|
|
15
|
+
* 'use client';
|
|
16
|
+
* import { authClient } from '@payez/next-mvp/client/better-auth-client';
|
|
17
|
+
* import { standardizedApi } from '@payez/next-mvp/lib/standardized-client-api';
|
|
18
|
+
*
|
|
19
|
+
* export function useAuth() {
|
|
20
|
+
* const { data: session } = useSession(); // Works in your app context
|
|
21
|
+
* // ... implementation
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @see {@link https://github.com/payez/next-mvp/blob/main/docs/centralized-auth-api-pattern.md#why-local-hooks-for-auth Complete documentation}
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { authClient } from '../client/better-auth-client';
|
|
29
|
+
import { useCallback } from 'react';
|
|
30
|
+
import { useRouter } from 'next/navigation';
|
|
31
|
+
import { standardizedApi, ApiResult } from '../lib/standardized-client-api';
|
|
32
|
+
|
|
33
|
+
// Custom session type matching NextAuth structure
|
|
34
|
+
export interface CustomSession {
|
|
35
|
+
user: {
|
|
36
|
+
id: string;
|
|
37
|
+
email: string;
|
|
38
|
+
roles?: string[];
|
|
39
|
+
twoFactorMethod?: string;
|
|
40
|
+
twoFactorSessionVerified?: boolean;
|
|
41
|
+
requiresTwoFactor?: boolean;
|
|
42
|
+
};
|
|
43
|
+
accessToken?: string;
|
|
44
|
+
refreshToken?: string;
|
|
45
|
+
expires: string;
|
|
46
|
+
error?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface UseAuthResult {
|
|
50
|
+
session: CustomSession | null;
|
|
51
|
+
status: 'loading' | 'authenticated' | 'unauthenticated';
|
|
52
|
+
isLoading: boolean;
|
|
53
|
+
isAuthenticated: boolean;
|
|
54
|
+
// API helper that automatically includes the auth token
|
|
55
|
+
apiCall: <T>(url: string, method?: 'GET' | 'POST' | 'PUT' | 'DELETE', data?: any) => Promise<ApiResult<T>>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function useAuth(): UseAuthResult {
|
|
59
|
+
const { data: sessionData, isPending } = authClient.useSession();
|
|
60
|
+
const session = sessionData;
|
|
61
|
+
const status = isPending ? 'loading' : session ? 'authenticated' : 'unauthenticated';
|
|
62
|
+
const router = useRouter();
|
|
63
|
+
|
|
64
|
+
const isLoading = status === 'loading';
|
|
65
|
+
const isAuthenticated = status === 'authenticated' && !!(session as any)?.accessToken;
|
|
66
|
+
|
|
67
|
+
// Handle sign out with redirect
|
|
68
|
+
const handleSignOut = useCallback(async () => {
|
|
69
|
+
await authClient.signOut();
|
|
70
|
+
router.push('/account-auth/login?error=SessionExpired');
|
|
71
|
+
}, [router]);
|
|
72
|
+
|
|
73
|
+
// API helper that automatically includes the auth token and uses standardized API
|
|
74
|
+
const apiCall = useCallback(
|
|
75
|
+
async <T>(url: string, method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'GET', data?: any): Promise<ApiResult<T>> => {
|
|
76
|
+
if (!(session as any)?.accessToken) {
|
|
77
|
+
console.error('[useAuth] No access token available');
|
|
78
|
+
throw new Error('Not authenticated');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
// Use standardized API which handles token refresh and validates response format
|
|
83
|
+
switch (method) {
|
|
84
|
+
case 'GET':
|
|
85
|
+
return await standardizedApi.get<T>(url, (session as any).accessToken!);
|
|
86
|
+
case 'POST':
|
|
87
|
+
return await standardizedApi.post<T>(url, data, (session as any).accessToken!);
|
|
88
|
+
case 'PUT':
|
|
89
|
+
return await standardizedApi.put<T>(url, data);
|
|
90
|
+
case 'DELETE':
|
|
91
|
+
return await standardizedApi.delete<T>(url);
|
|
92
|
+
default:
|
|
93
|
+
throw new Error(`Unsupported method: ${method}`);
|
|
94
|
+
}
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error('[useAuth] API call failed:', error);
|
|
97
|
+
|
|
98
|
+
// standardizedApi handles token refresh internally, but if we still get auth errors, sign out
|
|
99
|
+
if (error instanceof Error && error.message.includes('Authentication failed')) {
|
|
100
|
+
console.warn('[useAuth] Authentication failed, signing out...');
|
|
101
|
+
await handleSignOut();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
[(session as any)?.accessToken, handleSignOut]
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
session: session as CustomSession | null,
|
|
112
|
+
status,
|
|
113
|
+
isLoading,
|
|
114
|
+
isAuthenticated,
|
|
115
|
+
apiCall
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useAuthSettings Hook
|
|
3
|
-
*
|
|
4
|
-
* Client-side hook to access auth settings from the IDP config.
|
|
5
|
-
* Settings are passed through the session from server-side config.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
'use client';
|
|
9
|
-
|
|
10
|
-
import { authClient } from '../client/better-auth-client';
|
|
11
|
-
import type { AuthSettings } from '../lib/idp-client-config';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Extended session type that may include authSettings
|
|
15
|
-
*/
|
|
16
|
-
interface SessionWithAuthSettings {
|
|
17
|
-
authSettings?: AuthSettings;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Hook to access auth settings from the session.
|
|
22
|
-
*
|
|
23
|
-
* Auth settings are populated from IDP config on the server side
|
|
24
|
-
* and included in the session for client-side access.
|
|
25
|
-
*
|
|
26
|
-
* @returns AuthSettings or null if not available
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```tsx
|
|
30
|
-
* function MyComponent() {
|
|
31
|
-
* const authSettings = useAuthSettings();
|
|
32
|
-
*
|
|
33
|
-
* if (authSettings?.require2FA) {
|
|
34
|
-
* return <TwoFactorPrompt />;
|
|
35
|
-
* }
|
|
36
|
-
*
|
|
37
|
-
* return <Dashboard />;
|
|
38
|
-
* }
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
export function useAuthSettings(): AuthSettings | null {
|
|
42
|
-
const { data: session } = authClient.useSession();
|
|
43
|
-
|
|
44
|
-
if (!session) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Auth settings are included in the session from server-side config
|
|
49
|
-
const sessionWithSettings = session as unknown as SessionWithAuthSettings;
|
|
50
|
-
return sessionWithSettings.authSettings || null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Hook to check if 2FA is required based on auth settings.
|
|
55
|
-
*
|
|
56
|
-
* @returns boolean indicating if 2FA is required
|
|
57
|
-
*/
|
|
58
|
-
export function useRequires2FA(): boolean {
|
|
59
|
-
const authSettings = useAuthSettings();
|
|
60
|
-
// 257255: DELIBERATELY LEFT FAIL-CLOSED, and flagged rather than silently kept.
|
|
61
|
-
// QAPert proved any hardcoded fallback is wrong in one environment (same client
|
|
62
|
-
// is require_2fa TRUE on AKS, FALSE on dev-93), so `?? true` is not correct - it
|
|
63
|
-
// is merely the SAFE direction: it demands more auth rather than less, and
|
|
64
|
-
// flipping it to false would be fail-OPEN. The genuinely correct answer is to
|
|
65
|
-
// propagate "unknown" to the caller, which is a breaking signature change
|
|
66
|
-
// (boolean -> boolean | null) and needs its own decision. Tracked on 257255.
|
|
67
|
-
return authSettings?.require2FA ?? true;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Hook to get allowed 2FA methods.
|
|
72
|
-
*
|
|
73
|
-
* @returns Array of allowed 2FA method strings (e.g., ['email', 'sms', 'totp'])
|
|
74
|
-
*/
|
|
75
|
-
export function useAllowed2FAMethods(): string[] {
|
|
76
|
-
const authSettings = useAuthSettings();
|
|
77
|
-
// 257255 / v32(a) OFFER NOTHING YOU CANNOT CONFIRM.
|
|
78
|
-
// Was `?? ['email','sms']` - a fabricated method list rendered whenever the
|
|
79
|
-
// policy could not be read. On 2026-08-24 that told users to use email+sms
|
|
80
|
-
// while the database said emailcode+totp. An empty list is the honest answer;
|
|
81
|
-
// the caller must show "we could not load sign-in options" rather than guess.
|
|
82
|
-
return authSettings?.allowed2FAMethods ?? [];
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Hook to get session timeout settings.
|
|
87
|
-
*
|
|
88
|
-
* @returns Object with session and idle timeout minutes
|
|
89
|
-
*/
|
|
90
|
-
export function useSessionTimeouts(): { sessionTimeoutMinutes: number; idleTimeoutMinutes: number } {
|
|
91
|
-
const authSettings = useAuthSettings();
|
|
92
|
-
return {
|
|
93
|
-
sessionTimeoutMinutes: authSettings?.sessionTimeoutMinutes ?? 60,
|
|
94
|
-
idleTimeoutMinutes: authSettings?.idleTimeoutMinutes ?? 15,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Hook to check if remember me is allowed.
|
|
100
|
-
*
|
|
101
|
-
* @returns Object with allowRememberMe flag and rememberMeDays
|
|
102
|
-
*/
|
|
103
|
-
export function useRememberMeSettings(): { allowRememberMe: boolean; rememberMeDays: number } {
|
|
104
|
-
const authSettings = useAuthSettings();
|
|
105
|
-
return {
|
|
106
|
-
allowRememberMe: authSettings?.allowRememberMe ?? true,
|
|
107
|
-
rememberMeDays: authSettings?.rememberMeDays ?? 30,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* useAuthSettings Hook
|
|
3
|
+
*
|
|
4
|
+
* Client-side hook to access auth settings from the IDP config.
|
|
5
|
+
* Settings are passed through the session from server-side config.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use client';
|
|
9
|
+
|
|
10
|
+
import { authClient } from '../client/better-auth-client';
|
|
11
|
+
import type { AuthSettings } from '../lib/idp-client-config';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Extended session type that may include authSettings
|
|
15
|
+
*/
|
|
16
|
+
interface SessionWithAuthSettings {
|
|
17
|
+
authSettings?: AuthSettings;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Hook to access auth settings from the session.
|
|
22
|
+
*
|
|
23
|
+
* Auth settings are populated from IDP config on the server side
|
|
24
|
+
* and included in the session for client-side access.
|
|
25
|
+
*
|
|
26
|
+
* @returns AuthSettings or null if not available
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* function MyComponent() {
|
|
31
|
+
* const authSettings = useAuthSettings();
|
|
32
|
+
*
|
|
33
|
+
* if (authSettings?.require2FA) {
|
|
34
|
+
* return <TwoFactorPrompt />;
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* return <Dashboard />;
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function useAuthSettings(): AuthSettings | null {
|
|
42
|
+
const { data: session } = authClient.useSession();
|
|
43
|
+
|
|
44
|
+
if (!session) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Auth settings are included in the session from server-side config
|
|
49
|
+
const sessionWithSettings = session as unknown as SessionWithAuthSettings;
|
|
50
|
+
return sessionWithSettings.authSettings || null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Hook to check if 2FA is required based on auth settings.
|
|
55
|
+
*
|
|
56
|
+
* @returns boolean indicating if 2FA is required
|
|
57
|
+
*/
|
|
58
|
+
export function useRequires2FA(): boolean {
|
|
59
|
+
const authSettings = useAuthSettings();
|
|
60
|
+
// 257255: DELIBERATELY LEFT FAIL-CLOSED, and flagged rather than silently kept.
|
|
61
|
+
// QAPert proved any hardcoded fallback is wrong in one environment (same client
|
|
62
|
+
// is require_2fa TRUE on AKS, FALSE on dev-93), so `?? true` is not correct - it
|
|
63
|
+
// is merely the SAFE direction: it demands more auth rather than less, and
|
|
64
|
+
// flipping it to false would be fail-OPEN. The genuinely correct answer is to
|
|
65
|
+
// propagate "unknown" to the caller, which is a breaking signature change
|
|
66
|
+
// (boolean -> boolean | null) and needs its own decision. Tracked on 257255.
|
|
67
|
+
return authSettings?.require2FA ?? true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Hook to get allowed 2FA methods.
|
|
72
|
+
*
|
|
73
|
+
* @returns Array of allowed 2FA method strings (e.g., ['email', 'sms', 'totp'])
|
|
74
|
+
*/
|
|
75
|
+
export function useAllowed2FAMethods(): string[] {
|
|
76
|
+
const authSettings = useAuthSettings();
|
|
77
|
+
// 257255 / v32(a) OFFER NOTHING YOU CANNOT CONFIRM.
|
|
78
|
+
// Was `?? ['email','sms']` - a fabricated method list rendered whenever the
|
|
79
|
+
// policy could not be read. On 2026-08-24 that told users to use email+sms
|
|
80
|
+
// while the database said emailcode+totp. An empty list is the honest answer;
|
|
81
|
+
// the caller must show "we could not load sign-in options" rather than guess.
|
|
82
|
+
return authSettings?.allowed2FAMethods ?? [];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Hook to get session timeout settings.
|
|
87
|
+
*
|
|
88
|
+
* @returns Object with session and idle timeout minutes
|
|
89
|
+
*/
|
|
90
|
+
export function useSessionTimeouts(): { sessionTimeoutMinutes: number; idleTimeoutMinutes: number } {
|
|
91
|
+
const authSettings = useAuthSettings();
|
|
92
|
+
return {
|
|
93
|
+
sessionTimeoutMinutes: authSettings?.sessionTimeoutMinutes ?? 60,
|
|
94
|
+
idleTimeoutMinutes: authSettings?.idleTimeoutMinutes ?? 15,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Hook to check if remember me is allowed.
|
|
100
|
+
*
|
|
101
|
+
* @returns Object with allowRememberMe flag and rememberMeDays
|
|
102
|
+
*/
|
|
103
|
+
export function useRememberMeSettings(): { allowRememberMe: boolean; rememberMeDays: number } {
|
|
104
|
+
const authSettings = useAuthSettings();
|
|
105
|
+
return {
|
|
106
|
+
allowRememberMe: authSettings?.allowRememberMe ?? true,
|
|
107
|
+
rememberMeDays: authSettings?.rememberMeDays ?? 30,
|
|
108
|
+
};
|
|
109
|
+
}
|