@proveanything/smartlinks-auth-ui 0.4.5 → 0.4.6
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/components/SmartlinksAuthUI.d.ts.map +1 -1
- package/dist/index.esm.js +112 -52
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +112 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmartlinksAuthUI.d.ts","sourceRoot":"","sources":["../../src/components/SmartlinksAuthUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAY5D,OAAO,KAAK,EAAE,qBAAqB,EAAyF,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"SmartlinksAuthUI.d.ts","sourceRoot":"","sources":["../../src/components/SmartlinksAuthUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAY5D,OAAO,KAAK,EAAE,qBAAqB,EAAyF,MAAM,UAAU,CAAC;AA+L7I,QAAA,MAAM,mBAAmB,QAAa,OAAO,CAAC,IAAI,CAqBjD,CAAC;AAqDF,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAI/B,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAgyD5D,CAAC"}
|
package/dist/index.esm.js
CHANGED
|
@@ -12521,7 +12521,7 @@ function requiresEmailVerification(error) {
|
|
|
12521
12521
|
}
|
|
12522
12522
|
|
|
12523
12523
|
// VERSION: Update this when making changes to help identify which version is running
|
|
12524
|
-
const AUTH_UI_VERSION = '
|
|
12524
|
+
const AUTH_UI_VERSION = '45';
|
|
12525
12525
|
const LOG_PREFIX = `[SmartlinksAuthUI:v${AUTH_UI_VERSION}]`;
|
|
12526
12526
|
// Helper to check for URL auth params synchronously (runs during initialization)
|
|
12527
12527
|
// This prevents the form from flashing before detecting deep-link flows
|
|
@@ -12636,6 +12636,43 @@ const getNativeBridge = () => {
|
|
|
12636
12636
|
return native;
|
|
12637
12637
|
return null;
|
|
12638
12638
|
};
|
|
12639
|
+
// Helper to register an AuthKit.onAuthResult handler for a specific callbackId
|
|
12640
|
+
// The Android native app calls: window.AuthKit.onAuthResult(resultJson)
|
|
12641
|
+
const registerAuthKitCallback = (callbackId, onResult, timeoutMs = 5000, onTimeout) => {
|
|
12642
|
+
const bridge = window.AuthKit;
|
|
12643
|
+
if (!bridge) {
|
|
12644
|
+
console.warn('[AuthKit] No AuthKit bridge found, cannot register callback');
|
|
12645
|
+
onTimeout?.();
|
|
12646
|
+
return () => { };
|
|
12647
|
+
}
|
|
12648
|
+
// Store the previous handler so we can restore on cleanup
|
|
12649
|
+
const previousHandler = bridge.onAuthResult;
|
|
12650
|
+
const timeout = setTimeout(() => {
|
|
12651
|
+
// Restore previous handler on timeout
|
|
12652
|
+
bridge.onAuthResult = previousHandler;
|
|
12653
|
+
onTimeout?.();
|
|
12654
|
+
}, timeoutMs);
|
|
12655
|
+
bridge.onAuthResult = (resultOrJson) => {
|
|
12656
|
+
const result = typeof resultOrJson === 'string' ? JSON.parse(resultOrJson) : resultOrJson;
|
|
12657
|
+
// Match by callbackId if present, otherwise accept any result
|
|
12658
|
+
if (result.callbackId && result.callbackId !== callbackId) {
|
|
12659
|
+
// Not for us — pass through to previous handler if any
|
|
12660
|
+
if (typeof previousHandler === 'function') {
|
|
12661
|
+
previousHandler(resultOrJson);
|
|
12662
|
+
}
|
|
12663
|
+
return;
|
|
12664
|
+
}
|
|
12665
|
+
clearTimeout(timeout);
|
|
12666
|
+
// Restore previous handler
|
|
12667
|
+
bridge.onAuthResult = previousHandler;
|
|
12668
|
+
onResult(result);
|
|
12669
|
+
};
|
|
12670
|
+
// Return cleanup function
|
|
12671
|
+
return () => {
|
|
12672
|
+
clearTimeout(timeout);
|
|
12673
|
+
bridge.onAuthResult = previousHandler;
|
|
12674
|
+
};
|
|
12675
|
+
};
|
|
12639
12676
|
// Sign out from Google on the native side (clears cached Google account)
|
|
12640
12677
|
// This is fire-and-forget with a timeout - gracefully degrades if not supported
|
|
12641
12678
|
const signOutGoogleNative = async () => {
|
|
@@ -12644,21 +12681,7 @@ const signOutGoogleNative = async () => {
|
|
|
12644
12681
|
return;
|
|
12645
12682
|
const callbackId = `google_signout_${Date.now()}`;
|
|
12646
12683
|
return new Promise((resolve) => {
|
|
12647
|
-
|
|
12648
|
-
// Store original callback to restore later
|
|
12649
|
-
const originalCallback = window.smartlinksNativeCallback;
|
|
12650
|
-
window.smartlinksNativeCallback = (result) => {
|
|
12651
|
-
if (result.callbackId === callbackId) {
|
|
12652
|
-
clearTimeout(timeout);
|
|
12653
|
-
// Restore original callback
|
|
12654
|
-
window.smartlinksNativeCallback = originalCallback;
|
|
12655
|
-
resolve();
|
|
12656
|
-
}
|
|
12657
|
-
else if (originalCallback) {
|
|
12658
|
-
// Pass through to original callback for other messages
|
|
12659
|
-
originalCallback(result);
|
|
12660
|
-
}
|
|
12661
|
-
};
|
|
12684
|
+
registerAuthKitCallback(callbackId, () => resolve(), 3000, () => resolve());
|
|
12662
12685
|
const payload = JSON.stringify({
|
|
12663
12686
|
type: 'GOOGLE_SIGN_OUT',
|
|
12664
12687
|
callbackId,
|
|
@@ -12672,37 +12695,25 @@ const checkSilentGoogleSignIn = async (clientId, googleClientId) => {
|
|
|
12672
12695
|
return null;
|
|
12673
12696
|
const callbackId = `google_check_${Date.now()}`;
|
|
12674
12697
|
return new Promise((resolve) => {
|
|
12675
|
-
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
resolve({
|
|
12685
|
-
isSignedIn: result.isSignedIn || false,
|
|
12686
|
-
idToken: result.idToken,
|
|
12687
|
-
email: result.email,
|
|
12688
|
-
name: result.name,
|
|
12689
|
-
picture: result.picture,
|
|
12690
|
-
});
|
|
12691
|
-
}
|
|
12692
|
-
else {
|
|
12693
|
-
resolve(null);
|
|
12694
|
-
}
|
|
12698
|
+
registerAuthKitCallback(callbackId, (result) => {
|
|
12699
|
+
if (result.success) {
|
|
12700
|
+
resolve({
|
|
12701
|
+
isSignedIn: result.isSignedIn || false,
|
|
12702
|
+
idToken: result.idToken,
|
|
12703
|
+
email: result.email,
|
|
12704
|
+
name: result.name,
|
|
12705
|
+
picture: result.picture,
|
|
12706
|
+
});
|
|
12695
12707
|
}
|
|
12696
|
-
else
|
|
12697
|
-
|
|
12698
|
-
originalCallback(result);
|
|
12708
|
+
else {
|
|
12709
|
+
resolve(null);
|
|
12699
12710
|
}
|
|
12700
|
-
};
|
|
12711
|
+
}, 5000, () => resolve(null));
|
|
12701
12712
|
const payload = JSON.stringify({
|
|
12702
12713
|
type: 'GOOGLE_CHECK_SIGN_IN',
|
|
12703
12714
|
clientId,
|
|
12704
12715
|
googleClientId,
|
|
12705
|
-
serverClientId: googleClientId,
|
|
12716
|
+
serverClientId: googleClientId,
|
|
12706
12717
|
callbackId,
|
|
12707
12718
|
});
|
|
12708
12719
|
nativeBridge.checkGoogleSignIn(payload);
|
|
@@ -12746,6 +12757,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
12746
12757
|
const [contactSchema, setContactSchema] = useState(null); // Schema for registration fields
|
|
12747
12758
|
const [silentSignInChecked, setSilentSignInChecked] = useState(false); // Track if silent sign-in has been checked
|
|
12748
12759
|
const [googleFallbackToPopup, setGoogleFallbackToPopup] = useState(false); // Show popup fallback when FedCM is blocked/dismissed
|
|
12760
|
+
const [googleNativeTimedOut, setGoogleNativeTimedOut] = useState(false); // Native bridge callback timed out
|
|
12749
12761
|
const log = useMemo(() => createLoggerWrapper(logger), [logger]);
|
|
12750
12762
|
const api = new AuthAPI(apiEndpoint, clientId, clientName, logger);
|
|
12751
12763
|
const auth = useAuth();
|
|
@@ -13022,6 +13034,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13022
13034
|
if (urlMode === 'verifyEmail') {
|
|
13023
13035
|
log.log('Verifying email with token:', token);
|
|
13024
13036
|
const response = await api.verifyEmailWithToken(token);
|
|
13037
|
+
log.log('Email verification response:', { hasToken: !!response.token, hasUser: !!response.user, emailVerificationMode: response.emailVerificationMode, isNewUser: response.isNewUser });
|
|
13025
13038
|
// Get email verification mode from response or config
|
|
13026
13039
|
const verificationMode = response.emailVerificationMode || config?.emailVerification?.mode || 'verify-auto-login';
|
|
13027
13040
|
if ((verificationMode === 'verify-auto-login' || verificationMode === 'immediate') && response.token) {
|
|
@@ -13066,6 +13079,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13066
13079
|
log.log('Verifying reset token:', token);
|
|
13067
13080
|
// Verify token is valid, then show password reset form
|
|
13068
13081
|
const verifyResult = await api.verifyResetToken(token);
|
|
13082
|
+
log.log('Reset token verification result:', { valid: verifyResult.valid, hasEmail: !!verifyResult.email, message: verifyResult.message });
|
|
13069
13083
|
// Check if token is valid before proceeding
|
|
13070
13084
|
if (!verifyResult.valid) {
|
|
13071
13085
|
throw new Error(verifyResult.message || 'Invalid or expired token');
|
|
@@ -13083,6 +13097,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13083
13097
|
else if (urlMode === 'magicLink') {
|
|
13084
13098
|
log.log('Verifying magic link token:', token);
|
|
13085
13099
|
const response = await api.verifyMagicLink(token);
|
|
13100
|
+
log.log('Magic link verification response:', { hasToken: !!response.token, hasUser: !!response.user, isNewUser: response.isNewUser });
|
|
13086
13101
|
// Auto-login with magic link if token is provided
|
|
13087
13102
|
if (response.token) {
|
|
13088
13103
|
// Always await - auth.login now waits for parent ack automatically in iframe mode
|
|
@@ -13158,6 +13173,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13158
13173
|
const redirectUri = state.redirectUri || window.location.origin + window.location.pathname;
|
|
13159
13174
|
// Exchange authorization code for tokens
|
|
13160
13175
|
const response = await api.loginWithGoogleCode(code, redirectUri);
|
|
13176
|
+
log.log('Google OAuth code exchange response:', { hasToken: !!response.token, hasUser: !!response.user, isNewUser: response.isNewUser });
|
|
13161
13177
|
if (response.token) {
|
|
13162
13178
|
// Await login to ensure token is persisted before any navigation
|
|
13163
13179
|
await auth.login(response.token, response.user, response.accountData, response.isNewUser, getExpirationFromResponse(response));
|
|
@@ -13188,13 +13204,15 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13188
13204
|
setError(undefined);
|
|
13189
13205
|
setAuthSuccess(false);
|
|
13190
13206
|
try {
|
|
13207
|
+
log.log('Submitting email auth:', { mode, email: data.email });
|
|
13191
13208
|
const response = mode === 'login'
|
|
13192
13209
|
? await api.login(data.email, data.password)
|
|
13193
13210
|
: await api.register({
|
|
13194
13211
|
...data,
|
|
13195
13212
|
accountData: mode === 'register' ? accountData : undefined,
|
|
13196
|
-
redirectUrl: getRedirectUrl(),
|
|
13213
|
+
redirectUrl: getRedirectUrl(),
|
|
13197
13214
|
});
|
|
13215
|
+
log.log('Email auth response:', { mode, hasToken: !!response?.token, hasUser: !!response?.user, isNewUser: response?.isNewUser, requiresEmailVerification: response?.requiresEmailVerification, accountLocked: response?.accountLocked, emailVerificationMode: response?.emailVerificationMode });
|
|
13198
13216
|
// Defensive check: validate response before accessing properties
|
|
13199
13217
|
// SDK should throw on 401/error responses, but handle edge cases gracefully
|
|
13200
13218
|
if (!response) {
|
|
@@ -13407,21 +13425,20 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13407
13425
|
if (nativeBridge) {
|
|
13408
13426
|
log.log('Using native bridge for Google Sign-In');
|
|
13409
13427
|
const callbackId = `google_auth_${Date.now()}`;
|
|
13410
|
-
|
|
13411
|
-
|
|
13412
|
-
|
|
13413
|
-
log.log('Ignoring stale native callback:', result.callbackId);
|
|
13414
|
-
return;
|
|
13415
|
-
}
|
|
13416
|
-
log.log('Native callback received:', {
|
|
13428
|
+
// Register callback via AuthKit.onAuthResult (the native app calls this)
|
|
13429
|
+
const cleanup = registerAuthKitCallback(callbackId, async (result) => {
|
|
13430
|
+
log.log('Native Google auth result received:', {
|
|
13417
13431
|
success: result.success,
|
|
13418
13432
|
hasIdToken: !!result.idToken,
|
|
13419
13433
|
email: result.email,
|
|
13420
13434
|
error: result.error,
|
|
13435
|
+
callbackId: result.callbackId,
|
|
13421
13436
|
});
|
|
13437
|
+
setGoogleNativeTimedOut(false);
|
|
13422
13438
|
try {
|
|
13423
13439
|
if (result.success && result.idToken) {
|
|
13424
13440
|
const authResponse = await api.loginWithGoogle(result.idToken);
|
|
13441
|
+
log.log('Native Google login response:', { hasToken: !!authResponse.token, hasUser: !!authResponse.user, isNewUser: authResponse.isNewUser });
|
|
13425
13442
|
if (authResponse.token) {
|
|
13426
13443
|
await auth.login(authResponse.token, authResponse.user, authResponse.accountData, authResponse.isNewUser, getExpirationFromResponse(authResponse));
|
|
13427
13444
|
setAuthSuccess(true);
|
|
@@ -13444,7 +13461,12 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13444
13461
|
finally {
|
|
13445
13462
|
setLoading(false);
|
|
13446
13463
|
}
|
|
13447
|
-
}
|
|
13464
|
+
}, 30000, // 30s timeout for interactive Google Sign-In
|
|
13465
|
+
() => {
|
|
13466
|
+
log.log('Native Google Sign-In timed out after 30s');
|
|
13467
|
+
setLoading(false);
|
|
13468
|
+
setGoogleNativeTimedOut(true);
|
|
13469
|
+
});
|
|
13448
13470
|
const payloadObj = {
|
|
13449
13471
|
type: 'GOOGLE_SIGN_IN',
|
|
13450
13472
|
clientId,
|
|
@@ -13456,12 +13478,13 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13456
13478
|
requestServerAuthCode: false,
|
|
13457
13479
|
};
|
|
13458
13480
|
const payload = JSON.stringify(payloadObj);
|
|
13459
|
-
log.log('Invoking native signInWithGoogle');
|
|
13481
|
+
log.log('Invoking native signInWithGoogle with callbackId:', callbackId);
|
|
13460
13482
|
try {
|
|
13461
13483
|
nativeBridge.signInWithGoogle(payload);
|
|
13462
13484
|
}
|
|
13463
13485
|
catch (invokeError) {
|
|
13464
13486
|
console.error(`${LOG_PREFIX} Exception invoking signInWithGoogle:`, invokeError);
|
|
13487
|
+
cleanup(); // Clean up the callback registration
|
|
13465
13488
|
throw invokeError;
|
|
13466
13489
|
}
|
|
13467
13490
|
// Don't set loading to false - waiting for native callback
|
|
@@ -13506,6 +13529,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13506
13529
|
clearInterval(checkClosed);
|
|
13507
13530
|
try {
|
|
13508
13531
|
if (event.data.success && event.data.token) {
|
|
13532
|
+
log.log('Google proxy result received:', { success: true, hasUser: !!event.data.user, isNewUser: event.data.isNewUser });
|
|
13509
13533
|
const { token, user, accountData, isNewUser, expiresAt, expiresIn } = event.data;
|
|
13510
13534
|
const expiration = expiresAt || (expiresIn ? Date.now() + expiresIn : undefined);
|
|
13511
13535
|
await auth.login(token, user, accountData, isNewUser, expiration);
|
|
@@ -13633,6 +13657,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13633
13657
|
googleUserInfo: userInfo,
|
|
13634
13658
|
tokenType: 'access_token',
|
|
13635
13659
|
});
|
|
13660
|
+
log.log('Popup Google login response:', { hasToken: !!authResponse.token, hasUser: !!authResponse.user, isNewUser: authResponse.isNewUser });
|
|
13636
13661
|
if (authResponse.token) {
|
|
13637
13662
|
// Google OAuth can be login or signup - use isNewUser flag from backend if available
|
|
13638
13663
|
await auth.login(authResponse.token, authResponse.user, authResponse.accountData, authResponse.isNewUser, getExpirationFromResponse(authResponse));
|
|
@@ -13678,6 +13703,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13678
13703
|
try {
|
|
13679
13704
|
const idToken = response.credential;
|
|
13680
13705
|
const authResponse = await api.loginWithGoogle(idToken);
|
|
13706
|
+
log.log('OneTap Google login response:', { hasToken: !!authResponse.token, hasUser: !!authResponse.user, isNewUser: authResponse.isNewUser });
|
|
13681
13707
|
if (authResponse.token) {
|
|
13682
13708
|
// Google OAuth can be login or signup - use isNewUser flag from backend if available
|
|
13683
13709
|
await auth.login(authResponse.token, authResponse.user, authResponse.accountData, authResponse.isNewUser, getExpirationFromResponse(authResponse));
|
|
@@ -13744,6 +13770,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13744
13770
|
else {
|
|
13745
13771
|
// Verify code - Twilio identifies the verification by phone number
|
|
13746
13772
|
const response = await api.verifyPhoneCode(phoneNumber, verificationCode);
|
|
13773
|
+
log.log('Phone verification response:', { hasToken: !!response?.token, hasUser: !!response?.user, isNewUser: response?.isNewUser });
|
|
13747
13774
|
// Defensive validation: API may return undefined or error object on failure
|
|
13748
13775
|
if (!response) {
|
|
13749
13776
|
throw new Error('Verification failed - please check your code and try again');
|
|
@@ -14078,7 +14105,40 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
14078
14105
|
backgroundColor: 'transparent',
|
|
14079
14106
|
border: 'none',
|
|
14080
14107
|
cursor: 'pointer',
|
|
14081
|
-
}, children: "Dismiss" })] })), ((
|
|
14108
|
+
}, children: "Dismiss" })] })), googleNativeTimedOut && (jsxs("div", { style: {
|
|
14109
|
+
marginBottom: '1rem',
|
|
14110
|
+
padding: '0.75rem 1rem',
|
|
14111
|
+
borderRadius: '0.5rem',
|
|
14112
|
+
backgroundColor: resolvedTheme === 'dark' ? 'rgba(245, 158, 11, 0.1)' : 'rgba(245, 158, 11, 0.05)',
|
|
14113
|
+
border: `1px solid ${resolvedTheme === 'dark' ? 'rgba(245, 158, 11, 0.3)' : 'rgba(245, 158, 11, 0.2)'}`,
|
|
14114
|
+
}, children: [jsx("p", { style: {
|
|
14115
|
+
fontSize: '0.8125rem',
|
|
14116
|
+
color: resolvedTheme === 'dark' ? '#fbbf24' : '#92400e',
|
|
14117
|
+
marginBottom: '0.5rem',
|
|
14118
|
+
lineHeight: 1.4,
|
|
14119
|
+
}, children: 'Google sign-in didn\'t respond. You can try again or use another sign-in method.' }), jsx("button", { onClick: () => {
|
|
14120
|
+
setGoogleNativeTimedOut(false);
|
|
14121
|
+
handleGoogleLogin();
|
|
14122
|
+
}, style: {
|
|
14123
|
+
width: '100%',
|
|
14124
|
+
padding: '0.5rem 1rem',
|
|
14125
|
+
fontSize: '0.875rem',
|
|
14126
|
+
fontWeight: 500,
|
|
14127
|
+
color: '#fff',
|
|
14128
|
+
backgroundColor: '#4285F4',
|
|
14129
|
+
border: 'none',
|
|
14130
|
+
borderRadius: '0.375rem',
|
|
14131
|
+
cursor: 'pointer',
|
|
14132
|
+
}, children: 'Retry Google Sign-In' }), jsx("button", { onClick: () => setGoogleNativeTimedOut(false), style: {
|
|
14133
|
+
marginTop: '0.375rem',
|
|
14134
|
+
width: '100%',
|
|
14135
|
+
padding: '0.25rem',
|
|
14136
|
+
fontSize: '0.75rem',
|
|
14137
|
+
color: resolvedTheme === 'dark' ? '#64748b' : '#9ca3af',
|
|
14138
|
+
backgroundColor: 'transparent',
|
|
14139
|
+
border: 'none',
|
|
14140
|
+
cursor: 'pointer',
|
|
14141
|
+
}, children: 'Dismiss' })] })), (() => {
|
|
14082
14142
|
const emailDisplayMode = config?.emailDisplayMode || 'form';
|
|
14083
14143
|
const providerOrder = config?.providerOrder || (config?.enabledProviders || enabledProviders);
|
|
14084
14144
|
const actualProviders = config?.enabledProviders || enabledProviders;
|