@payez/next-mvp 4.0.21 → 4.0.23
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/auth/better-auth.js +1 -1
- package/dist/client/AuthContext.d.ts +1 -2
- package/dist/client/AuthContext.js +2 -2
- package/dist/client/better-auth-client.d.ts +8 -0
- package/dist/client/better-auth-client.js +15 -0
- package/dist/components/account/MobileNavDrawer.js +1 -1
- package/dist/hooks/useAvailableProviders.d.ts +4 -5
- package/dist/hooks/useAvailableProviders.js +7 -8
- package/dist/hooks/usePublicAuthSettings.d.ts +4 -4
- package/dist/hooks/usePublicAuthSettings.js +6 -6
- package/dist/lib/idp-client-config.d.ts +4 -0
- package/dist/lib/idp-client-config.js +14 -0
- package/dist/lib/startup-init.js +21 -19
- package/dist/routes/auth/settings.d.ts +1 -1
- package/dist/routes/auth/settings.js +2 -2
- package/dist/server/auth.js +1 -1
- package/package.json +1 -1
- package/src/auth/better-auth.ts +271 -271
- package/src/client/AuthContext.tsx +3 -4
- package/src/client/better-auth-client.ts +14 -0
- package/src/components/account/MobileNavDrawer.tsx +2 -2
- package/src/hooks/useAvailableProviders.ts +5 -7
- package/src/hooks/usePublicAuthSettings.ts +6 -6
- package/src/lib/idp-client-config.ts +539 -526
- package/src/lib/startup-init.ts +246 -243
- package/src/routes/auth/settings.ts +3 -3
- package/src/server/auth.ts +81 -81
package/dist/auth/better-auth.js
CHANGED
|
@@ -217,7 +217,7 @@ async function getBetterAuthInstance() {
|
|
|
217
217
|
if (cachedInstance)
|
|
218
218
|
return cachedInstance;
|
|
219
219
|
if (!initPromise) {
|
|
220
|
-
initPromise = (0, idp_client_config_1.getIDPClientConfig)().then(config => {
|
|
220
|
+
initPromise = (0, idp_client_config_1.getIDPClientConfig)(true).then(config => {
|
|
221
221
|
const instance = createBetterAuthInstance(config);
|
|
222
222
|
exports.__betterAuthInstance = cachedInstance = instance;
|
|
223
223
|
console.log('[BETTER_AUTH] Instance created for', config.clientSlug || config.clientId);
|
|
@@ -4,9 +4,8 @@ interface AuthProviderProps {
|
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
config?: Partial<AuthConfig>;
|
|
6
6
|
/**
|
|
7
|
-
* If true, providers will be
|
|
7
|
+
* If true, providers will be loaded dynamically from IDP config
|
|
8
8
|
* instead of using the static providers array from config.
|
|
9
|
-
* Defaults to true for dynamic provider loading from IDP.
|
|
10
9
|
*/
|
|
11
10
|
useDynamicProviders?: boolean;
|
|
12
11
|
}
|
|
@@ -18,7 +18,7 @@ const defaultConfig = {
|
|
|
18
18
|
enableEmailSignup: true,
|
|
19
19
|
allowPasswordReset: true,
|
|
20
20
|
};
|
|
21
|
-
// Map
|
|
21
|
+
// Map provider IDs to our FederatedProvider type
|
|
22
22
|
const PROVIDER_MAP = {
|
|
23
23
|
'google': 'google',
|
|
24
24
|
'apple': 'apple',
|
|
@@ -42,7 +42,7 @@ function AuthProvider({ children, config, useDynamicProviders = true }) {
|
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
}));
|
|
45
|
-
//
|
|
45
|
+
// Load available providers on mount
|
|
46
46
|
(0, react_1.useEffect)(() => {
|
|
47
47
|
if (!useDynamicProviders)
|
|
48
48
|
return;
|
|
@@ -956,6 +956,14 @@ export declare const useSession: () => {
|
|
|
956
956
|
code?: string | undefined;
|
|
957
957
|
message?: string | undefined;
|
|
958
958
|
}, FetchOptions["throw"] extends true ? true : false>>;
|
|
959
|
+
/**
|
|
960
|
+
* Sign in with a specific OAuth provider via direct redirect.
|
|
961
|
+
*
|
|
962
|
+
* better-auth exposes per-provider endpoints at /api/auth/sign-in/{provider}
|
|
963
|
+
* (e.g. /api/auth/sign-in/google). The generic signIn.social() method POSTs
|
|
964
|
+
* to /api/auth/sign-in/social which doesn't exist — use this instead.
|
|
965
|
+
*/
|
|
966
|
+
export declare function signInWithProvider(provider: string, callbackURL?: string): void;
|
|
959
967
|
/**
|
|
960
968
|
* NextAuth-compatible useSession wrapper.
|
|
961
969
|
*
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.signOut = exports.signIn = exports.useSession = exports.authClient = void 0;
|
|
13
|
+
exports.signInWithProvider = signInWithProvider;
|
|
13
14
|
exports.useSessionCompat = useSessionCompat;
|
|
14
15
|
exports.signOutCompat = signOutCompat;
|
|
15
16
|
const react_1 = require("better-auth/react");
|
|
@@ -19,6 +20,20 @@ exports.authClient = (0, react_1.createAuthClient)({
|
|
|
19
20
|
});
|
|
20
21
|
// Convenience exports
|
|
21
22
|
exports.useSession = exports.authClient.useSession, exports.signIn = exports.authClient.signIn, exports.signOut = exports.authClient.signOut;
|
|
23
|
+
/**
|
|
24
|
+
* Sign in with a specific OAuth provider via direct redirect.
|
|
25
|
+
*
|
|
26
|
+
* better-auth exposes per-provider endpoints at /api/auth/sign-in/{provider}
|
|
27
|
+
* (e.g. /api/auth/sign-in/google). The generic signIn.social() method POSTs
|
|
28
|
+
* to /api/auth/sign-in/social which doesn't exist — use this instead.
|
|
29
|
+
*/
|
|
30
|
+
function signInWithProvider(provider, callbackURL) {
|
|
31
|
+
const params = new URLSearchParams();
|
|
32
|
+
if (callbackURL)
|
|
33
|
+
params.set('callbackURL', callbackURL);
|
|
34
|
+
const qs = params.toString();
|
|
35
|
+
window.location.href = `/api/auth/sign-in/${provider}${qs ? '?' + qs : ''}`;
|
|
36
|
+
}
|
|
22
37
|
/**
|
|
23
38
|
* NextAuth-compatible useSession wrapper.
|
|
24
39
|
*
|
|
@@ -44,7 +44,7 @@ function MobileNavDrawer({ isOpen, onClose, navItems, customSections, basePath =
|
|
|
44
44
|
onSignIn();
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
47
|
-
better_auth_client_1.
|
|
47
|
+
(0, better_auth_client_1.signInWithProvider)('google', signInCallbackUrl);
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
50
|
const handleSectionItemClick = (item) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useAvailableProviders Hook
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Returns the list of OAuth providers configured for this client.
|
|
5
|
+
* Ensures UI only shows buttons for providers that are enabled in IDP.
|
|
6
6
|
*/
|
|
7
7
|
import type { FederatedProvider } from '../types/auth';
|
|
8
8
|
export interface UseAvailableProvidersResult {
|
|
@@ -12,10 +12,9 @@ export interface UseAvailableProvidersResult {
|
|
|
12
12
|
rawProviders: Record<string, any> | null;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Hook to get available OAuth providers
|
|
15
|
+
* Hook to get available federated OAuth providers.
|
|
16
16
|
*
|
|
17
|
-
* Returns only the providers that are
|
|
18
|
-
* which reflects what's enabled in IDP config.
|
|
17
|
+
* Returns only the providers that are enabled in IDP config.
|
|
19
18
|
*
|
|
20
19
|
* @example
|
|
21
20
|
* ```tsx
|
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* useAvailableProviders Hook
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Returns the list of OAuth providers configured for this client.
|
|
6
|
+
* Ensures UI only shows buttons for providers that are enabled in IDP.
|
|
7
7
|
*/
|
|
8
8
|
'use client';
|
|
9
9
|
/**
|
|
10
10
|
* useAvailableProviders Hook
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Returns the list of OAuth providers configured for this client.
|
|
13
|
+
* Ensures UI only shows buttons for providers that are enabled in IDP.
|
|
14
14
|
*/
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.useAvailableProviders = useAvailableProviders;
|
|
17
17
|
exports.useIsProviderAvailable = useIsProviderAvailable;
|
|
18
18
|
const react_1 = require("react");
|
|
19
|
-
// Map
|
|
19
|
+
// Map provider IDs to our FederatedProvider type
|
|
20
20
|
const PROVIDER_MAP = {
|
|
21
21
|
'google': 'google',
|
|
22
22
|
'apple': 'apple',
|
|
@@ -28,10 +28,9 @@ const PROVIDER_MAP = {
|
|
|
28
28
|
// Providers we support in UI (excludes credentials)
|
|
29
29
|
const OAUTH_PROVIDERS = ['google', 'apple', 'facebook', 'github', 'azure-ad', 'microsoft-entra-id'];
|
|
30
30
|
/**
|
|
31
|
-
* Hook to get available OAuth providers
|
|
31
|
+
* Hook to get available federated OAuth providers.
|
|
32
32
|
*
|
|
33
|
-
* Returns only the providers that are
|
|
34
|
-
* which reflects what's enabled in IDP config.
|
|
33
|
+
* Returns only the providers that are enabled in IDP config.
|
|
35
34
|
*
|
|
36
35
|
* @example
|
|
37
36
|
* ```tsx
|
|
@@ -8,7 +8,7 @@ import type { FederatedProvider } from '../types/auth';
|
|
|
8
8
|
export interface PublicAuthSettings {
|
|
9
9
|
enabledProviders: FederatedProvider[];
|
|
10
10
|
allowPublicRegistration: boolean;
|
|
11
|
-
|
|
11
|
+
allowFederatedLogin: boolean;
|
|
12
12
|
enablePasswordReset: boolean;
|
|
13
13
|
require2FA: boolean;
|
|
14
14
|
allowed2FAMethods: string[];
|
|
@@ -30,7 +30,7 @@ export interface UsePublicAuthSettingsResult {
|
|
|
30
30
|
*
|
|
31
31
|
* return (
|
|
32
32
|
* <>
|
|
33
|
-
* {settings?.
|
|
33
|
+
* {settings?.allowFederatedLogin && (
|
|
34
34
|
* <FederatedAuthSection providers={settings.enabledProviders} />
|
|
35
35
|
* )}
|
|
36
36
|
* {settings?.allowPublicRegistration && (
|
|
@@ -43,9 +43,9 @@ export interface UsePublicAuthSettingsResult {
|
|
|
43
43
|
*/
|
|
44
44
|
export declare function usePublicAuthSettings(): UsePublicAuthSettingsResult;
|
|
45
45
|
/**
|
|
46
|
-
* Hook to check if
|
|
46
|
+
* Hook to check if federated (OAuth) login is enabled.
|
|
47
47
|
*/
|
|
48
|
-
export declare function
|
|
48
|
+
export declare function useFederatedLoginEnabled(): boolean;
|
|
49
49
|
/**
|
|
50
50
|
* Hook to check if public registration is enabled.
|
|
51
51
|
*/
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.usePublicAuthSettings = usePublicAuthSettings;
|
|
17
|
-
exports.
|
|
17
|
+
exports.useFederatedLoginEnabled = useFederatedLoginEnabled;
|
|
18
18
|
exports.usePublicRegistrationEnabled = usePublicRegistrationEnabled;
|
|
19
19
|
exports.usePasswordResetEnabled = usePasswordResetEnabled;
|
|
20
20
|
const react_1 = require("react");
|
|
@@ -30,7 +30,7 @@ const PROVIDER_MAP = {
|
|
|
30
30
|
const DEFAULT_SETTINGS = {
|
|
31
31
|
enabledProviders: [],
|
|
32
32
|
allowPublicRegistration: true,
|
|
33
|
-
|
|
33
|
+
allowFederatedLogin: false,
|
|
34
34
|
enablePasswordReset: true,
|
|
35
35
|
require2FA: true,
|
|
36
36
|
allowed2FAMethods: ['email', 'sms'],
|
|
@@ -47,7 +47,7 @@ const DEFAULT_SETTINGS = {
|
|
|
47
47
|
*
|
|
48
48
|
* return (
|
|
49
49
|
* <>
|
|
50
|
-
* {settings?.
|
|
50
|
+
* {settings?.allowFederatedLogin && (
|
|
51
51
|
* <FederatedAuthSection providers={settings.enabledProviders} />
|
|
52
52
|
* )}
|
|
53
53
|
* {settings?.allowPublicRegistration && (
|
|
@@ -109,11 +109,11 @@ function usePublicAuthSettings() {
|
|
|
109
109
|
return { settings, isLoading, error };
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
|
-
* Hook to check if
|
|
112
|
+
* Hook to check if federated (OAuth) login is enabled.
|
|
113
113
|
*/
|
|
114
|
-
function
|
|
114
|
+
function useFederatedLoginEnabled() {
|
|
115
115
|
const { settings } = usePublicAuthSettings();
|
|
116
|
-
return settings?.
|
|
116
|
+
return settings?.allowFederatedLogin ?? false;
|
|
117
117
|
}
|
|
118
118
|
/**
|
|
119
119
|
* Hook to check if public registration is enabled.
|
|
@@ -69,6 +69,10 @@ export declare function getIDPClientConfig(forceRefresh?: boolean): Promise<IDPC
|
|
|
69
69
|
* Clear the config cache (useful for testing or forced refresh)
|
|
70
70
|
*/
|
|
71
71
|
export declare function clearConfigCache(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Clear the Redis config cache so the next fetch always goes to IDP.
|
|
74
|
+
*/
|
|
75
|
+
export declare function clearConfigRedisCache(): Promise<void>;
|
|
72
76
|
/**
|
|
73
77
|
* Get enabled OAuth providers from config
|
|
74
78
|
*/
|
|
@@ -24,6 +24,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.getIDPClientConfig = getIDPClientConfig;
|
|
26
26
|
exports.clearConfigCache = clearConfigCache;
|
|
27
|
+
exports.clearConfigRedisCache = clearConfigRedisCache;
|
|
27
28
|
exports.getEnabledProviders = getEnabledProviders;
|
|
28
29
|
require("server-only");
|
|
29
30
|
const crypto_1 = require("crypto");
|
|
@@ -176,6 +177,19 @@ function clearConfigCache() {
|
|
|
176
177
|
cachedConfig = null;
|
|
177
178
|
cacheExpiry = 0;
|
|
178
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Clear the Redis config cache so the next fetch always goes to IDP.
|
|
182
|
+
*/
|
|
183
|
+
async function clearConfigRedisCache() {
|
|
184
|
+
try {
|
|
185
|
+
const key = getRedisConfigKey();
|
|
186
|
+
await redis_1.default.del(key);
|
|
187
|
+
console.log('[IDP_CONFIG] Redis cache cleared:', key);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
console.warn('[IDP_CONFIG] Failed to clear Redis cache:', error);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
179
193
|
/**
|
|
180
194
|
* Get enabled OAuth providers from config
|
|
181
195
|
*/
|
package/dist/lib/startup-init.js
CHANGED
|
@@ -136,6 +136,8 @@ async function performInitialization() {
|
|
|
136
136
|
try {
|
|
137
137
|
// Step 1: Fetch full client config from IDP (includes secret, providers, settings)
|
|
138
138
|
console.log('[STARTUP] Step 1/2: Fetching client config from IDP...');
|
|
139
|
+
// Clear any stale Redis cache so startup always gets fresh IDP data
|
|
140
|
+
await (0, idp_client_config_1.clearConfigRedisCache)();
|
|
139
141
|
try {
|
|
140
142
|
const config = await (0, idp_client_config_1.getIDPClientConfig)(true);
|
|
141
143
|
cachedIDPConfig = config;
|
|
@@ -206,25 +208,25 @@ async function performInitialization() {
|
|
|
206
208
|
const connectionLine = isConnectionError
|
|
207
209
|
? '║ 🔌 CONNECTION REFUSED - IDP appears to be down ║\n║ ║\n'
|
|
208
210
|
: '';
|
|
209
|
-
console.error(`
|
|
210
|
-
╔══════════════════════════════════════════════════════════════╗
|
|
211
|
-
║ ❌ FATAL: NEXTAUTH_SECRET NOT AVAILABLE ║
|
|
212
|
-
║ ║
|
|
213
|
-
║ The app cannot start without a valid NEXTAUTH_SECRET. ║
|
|
214
|
-
║ This should be fetched from IDP at startup. ║
|
|
215
|
-
║ ║
|
|
216
|
-
${connectionLine}║ Possible causes: ║
|
|
217
|
-
║ • IDP is not running or unreachable ║
|
|
218
|
-
║ • CLIENT_ID is not registered in IDP ║
|
|
219
|
-
║ • IDP_URL is incorrect ║
|
|
220
|
-
║ • Network connectivity issue ║
|
|
221
|
-
║ ║
|
|
222
|
-
║ Current config: ║
|
|
223
|
-
║ • IDP_URL: ${idpUrl}║
|
|
224
|
-
║ • CLIENT_ID: ${clientId}║
|
|
225
|
-
╚══════════════════════════════════════════════════════════════╝
|
|
226
|
-
|
|
227
|
-
[STARTUP] Error: ${errorMsg}
|
|
211
|
+
console.error(`
|
|
212
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
213
|
+
║ ❌ FATAL: NEXTAUTH_SECRET NOT AVAILABLE ║
|
|
214
|
+
║ ║
|
|
215
|
+
║ The app cannot start without a valid NEXTAUTH_SECRET. ║
|
|
216
|
+
║ This should be fetched from IDP at startup. ║
|
|
217
|
+
║ ║
|
|
218
|
+
${connectionLine}║ Possible causes: ║
|
|
219
|
+
║ • IDP is not running or unreachable ║
|
|
220
|
+
║ • CLIENT_ID is not registered in IDP ║
|
|
221
|
+
║ • IDP_URL is incorrect ║
|
|
222
|
+
║ • Network connectivity issue ║
|
|
223
|
+
║ ║
|
|
224
|
+
║ Current config: ║
|
|
225
|
+
║ • IDP_URL: ${idpUrl}║
|
|
226
|
+
║ • CLIENT_ID: ${clientId}║
|
|
227
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
228
|
+
|
|
229
|
+
[STARTUP] Error: ${errorMsg}
|
|
228
230
|
`);
|
|
229
231
|
// Re-throw so callers know initialization failed
|
|
230
232
|
throw lastInitError;
|
|
@@ -8,7 +8,7 @@ import { NextResponse } from 'next/server';
|
|
|
8
8
|
export interface PublicAuthSettings {
|
|
9
9
|
enabledProviders: string[];
|
|
10
10
|
allowPublicRegistration: boolean;
|
|
11
|
-
|
|
11
|
+
allowFederatedLogin: boolean;
|
|
12
12
|
enablePasswordReset: boolean;
|
|
13
13
|
require2FA: boolean;
|
|
14
14
|
allowed2FAMethods: string[];
|
|
@@ -25,7 +25,7 @@ async function GET() {
|
|
|
25
25
|
.map(p => p.provider) ?? [],
|
|
26
26
|
// Registration - default to true if not specified
|
|
27
27
|
allowPublicRegistration: true, // Could come from config.authSettings in future
|
|
28
|
-
|
|
28
|
+
allowFederatedLogin: config.oauthProviders?.some(p => p.enabled) ?? false,
|
|
29
29
|
// Password reset
|
|
30
30
|
enablePasswordReset: true, // Could come from config.authSettings in future
|
|
31
31
|
// 2FA
|
|
@@ -45,7 +45,7 @@ async function GET() {
|
|
|
45
45
|
data: {
|
|
46
46
|
enabledProviders: [],
|
|
47
47
|
allowPublicRegistration: true,
|
|
48
|
-
|
|
48
|
+
allowFederatedLogin: false,
|
|
49
49
|
enablePasswordReset: true,
|
|
50
50
|
require2FA: true,
|
|
51
51
|
allowed2FAMethods: ['email', 'sms'],
|
package/dist/server/auth.js
CHANGED
|
@@ -57,7 +57,7 @@ async function getAuthInstance() {
|
|
|
57
57
|
if (authInstance)
|
|
58
58
|
return authInstance;
|
|
59
59
|
if (!authInitPromise) {
|
|
60
|
-
authInitPromise = (0, idp_client_config_1.getIDPClientConfig)().then(config => {
|
|
60
|
+
authInitPromise = (0, idp_client_config_1.getIDPClientConfig)(true).then(config => {
|
|
61
61
|
authInstance = (0, better_auth_1.createBetterAuthInstance)(config);
|
|
62
62
|
return authInstance;
|
|
63
63
|
});
|