@proveanything/smartlinks-auth-ui 0.1.44 → 0.1.45
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/context/AuthContext.d.ts +1 -1
- package/dist/context/AuthContext.d.ts.map +1 -1
- package/dist/index.esm.js +98 -27
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +98 -27
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.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;AAW5D,OAAO,KAAK,EAAE,qBAAqB,EAAyF,MAAM,UAAU,CAAC;AAgI7I,QAAA,MAAM,mBAAmB,QAAa,OAAO,CAAC,IAAI,CA+CjD,CAAC;AAyFF,OAAO,EAAE,mBAAmB,EAAE,CAAC;AA8B/B,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,
|
|
1
|
+
{"version":3,"file":"SmartlinksAuthUI.d.ts","sourceRoot":"","sources":["../../src/components/SmartlinksAuthUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAW5D,OAAO,KAAK,EAAE,qBAAqB,EAAyF,MAAM,UAAU,CAAC;AAgI7I,QAAA,MAAM,mBAAmB,QAAa,OAAO,CAAC,IAAI,CA+CjD,CAAC;AAyFF,OAAO,EAAE,mBAAmB,EAAE,CAAC;AA8B/B,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA8oD5D,CAAC"}
|
|
@@ -15,7 +15,7 @@ interface AuthContextValue {
|
|
|
15
15
|
contactId: string | null;
|
|
16
16
|
getContact: (forceRefresh?: boolean) => Promise<ContactResponse | null>;
|
|
17
17
|
updateContactCustomFields: (customFields: Record<string, any>) => Promise<ContactResponse>;
|
|
18
|
-
login: (token: string, user: AuthUser, accountData?: Record<string, any>, isNewUser?: boolean, expiresAt?: number) => Promise<void>;
|
|
18
|
+
login: (token: string, user: AuthUser, accountData?: Record<string, any>, isNewUser?: boolean, expiresAt?: number, waitForParentAck?: boolean) => Promise<void>;
|
|
19
19
|
logout: () => Promise<void>;
|
|
20
20
|
getToken: () => Promise<string | null>;
|
|
21
21
|
getTokenInfo: () => Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAGnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,KAAK,EAAE,QAAQ,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAErF,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IAGnB,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACxE,yBAAyB,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAG3F,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAGnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,KAAK,EAAE,QAAQ,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAErF,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IAGnB,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACxE,yBAAyB,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAG3F,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChK,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvC,YAAY,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC5F,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACrE,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACnD,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,iBAAiB,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,MAAM,IAAI,CAAC;IACrE,iBAAiB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3C;AAID,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAq7BpD,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,gBAM1B,CAAC"}
|
package/dist/index.esm.js
CHANGED
|
@@ -11840,7 +11840,42 @@ collectionId, enableContactSync, enableInteractionTracking, interactionAppId, in
|
|
|
11840
11840
|
unsubscribe();
|
|
11841
11841
|
};
|
|
11842
11842
|
}, [proxyMode, notifyAuthStateChange]);
|
|
11843
|
-
|
|
11843
|
+
// Helper: Send login to parent and wait for acknowledgment
|
|
11844
|
+
// Used for deep-link flows (email verification, magic link) where we need to ensure
|
|
11845
|
+
// the parent has persisted the session before redirecting (which causes page reload)
|
|
11846
|
+
const notifyParentLoginAndWait = async (authToken, authUser, authAccountData, timeoutMs = 5000) => {
|
|
11847
|
+
return new Promise((resolve) => {
|
|
11848
|
+
const messageId = `login-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
11849
|
+
const handleAck = (event) => {
|
|
11850
|
+
if (event.data?.type === 'smartlinks:authkit:login-acknowledged' &&
|
|
11851
|
+
event.data?.messageId === messageId) {
|
|
11852
|
+
window.removeEventListener('message', handleAck);
|
|
11853
|
+
clearTimeout(timeoutHandle);
|
|
11854
|
+
if (event.data.success) {
|
|
11855
|
+
console.log('[AuthContext] Parent acknowledged login successfully');
|
|
11856
|
+
}
|
|
11857
|
+
else {
|
|
11858
|
+
console.warn('[AuthContext] Parent rejected login:', event.data.error);
|
|
11859
|
+
}
|
|
11860
|
+
resolve();
|
|
11861
|
+
}
|
|
11862
|
+
};
|
|
11863
|
+
const timeoutHandle = setTimeout(() => {
|
|
11864
|
+
window.removeEventListener('message', handleAck);
|
|
11865
|
+
console.warn('[AuthContext] Parent login acknowledgment timed out, proceeding anyway');
|
|
11866
|
+
resolve(); // Don't block forever - fallback to current behavior
|
|
11867
|
+
}, timeoutMs);
|
|
11868
|
+
window.addEventListener('message', handleAck);
|
|
11869
|
+
console.log('[AuthContext] Sending login to parent, awaiting acknowledgment:', messageId);
|
|
11870
|
+
iframe.sendParentCustom('smartlinks:authkit:login', {
|
|
11871
|
+
messageId,
|
|
11872
|
+
token: authToken,
|
|
11873
|
+
user: authUser,
|
|
11874
|
+
accountData: authAccountData || null
|
|
11875
|
+
});
|
|
11876
|
+
});
|
|
11877
|
+
};
|
|
11878
|
+
const login = useCallback(async (authToken, authUser, authAccountData, isNewUser, expiresAt, waitForParentAck) => {
|
|
11844
11879
|
try {
|
|
11845
11880
|
// Only persist to storage in standalone mode
|
|
11846
11881
|
if (!proxyMode) {
|
|
@@ -11861,12 +11896,20 @@ collectionId, enableContactSync, enableInteractionTracking, interactionAppId, in
|
|
|
11861
11896
|
pendingVerificationRef.current = false;
|
|
11862
11897
|
// Cross-iframe auth state synchronization
|
|
11863
11898
|
if (iframe.isIframe()) {
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
|
|
11899
|
+
if (waitForParentAck) {
|
|
11900
|
+
// For deep-link flows: wait for parent to validate and persist session before redirect
|
|
11901
|
+
console.log('[AuthContext] Notifying parent of login and waiting for acknowledgment');
|
|
11902
|
+
await notifyParentLoginAndWait(authToken, authUser, authAccountData);
|
|
11903
|
+
}
|
|
11904
|
+
else {
|
|
11905
|
+
// For interactive flows: fire-and-forget is fine (no redirect follows)
|
|
11906
|
+
console.log('[AuthContext] Notifying parent of login via postMessage');
|
|
11907
|
+
iframe.sendParentCustom('smartlinks:authkit:login', {
|
|
11908
|
+
token: authToken,
|
|
11909
|
+
user: authUser,
|
|
11910
|
+
accountData: authAccountData || null
|
|
11911
|
+
});
|
|
11912
|
+
}
|
|
11870
11913
|
}
|
|
11871
11914
|
notifyAuthStateChange('LOGIN', authUser, authToken, authAccountData || null, null, true);
|
|
11872
11915
|
// Sync contact (non-blocking)
|
|
@@ -12192,7 +12235,7 @@ const useAuth = () => {
|
|
|
12192
12235
|
};
|
|
12193
12236
|
|
|
12194
12237
|
// VERSION: Update this when making changes to help identify which version is running
|
|
12195
|
-
const AUTH_UI_VERSION = '
|
|
12238
|
+
const AUTH_UI_VERSION = '41';
|
|
12196
12239
|
const LOG_PREFIX = `[SmartlinksAuthUI:v${AUTH_UI_VERSION}]`;
|
|
12197
12240
|
// Helper to calculate expiration from AuthResponse
|
|
12198
12241
|
const getExpirationFromResponse = (response) => {
|
|
@@ -12779,19 +12822,30 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
12779
12822
|
const verificationMode = response.emailVerificationMode || config?.emailVerification?.mode || 'verify-auto-login';
|
|
12780
12823
|
if ((verificationMode === 'verify-auto-login' || verificationMode === 'immediate') && response.token) {
|
|
12781
12824
|
// Auto-login modes: Log the user in immediately if token is provided
|
|
12782
|
-
//
|
|
12783
|
-
await
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
// Clear the URL parameters
|
|
12825
|
+
// In proxy mode, wait for parent to acknowledge (validate & persist) before redirect
|
|
12826
|
+
// MUST await to ensure session is ready before any redirect
|
|
12827
|
+
await auth.login(response.token, response.user, response.accountData, true, getExpirationFromResponse(response), proxyMode // waitForParentAck - ensures parent has validated/persisted before redirect
|
|
12828
|
+
);
|
|
12829
|
+
// Clean URL parameters regardless of redirect
|
|
12788
12830
|
const cleanUrl = window.location.href.split('?')[0];
|
|
12789
12831
|
window.history.replaceState({}, document.title, cleanUrl);
|
|
12790
|
-
// For email verification deep links, redirect immediately if configured
|
|
12791
|
-
// (user came from an email link, so redirect is expected behavior)
|
|
12792
12832
|
if (redirectUrl) {
|
|
12833
|
+
// Redirect to clean URL and resume flow
|
|
12834
|
+
// In proxy mode: parent already validated & persisted via acknowledgment in auth.login()
|
|
12835
|
+
// In standalone mode: session saved to IndexedDB, AuthContext will restore on reload
|
|
12836
|
+
// Either way: DON'T call onAuthSuccess (redirect wipes page state)
|
|
12837
|
+
log.log('Email verification complete, redirecting to:', redirectUrl);
|
|
12793
12838
|
performRedirect(redirectUrl, 'email-verified');
|
|
12794
12839
|
}
|
|
12840
|
+
else {
|
|
12841
|
+
// No redirect configured: show success UI
|
|
12842
|
+
setAuthSuccess(true);
|
|
12843
|
+
setSuccessMessage('Email verified successfully! You are now logged in.');
|
|
12844
|
+
if (!proxyMode) {
|
|
12845
|
+
// Only call onAuthSuccess in standalone mode (proxy mode used postMessage)
|
|
12846
|
+
onAuthSuccess(response.token, response.user, response.accountData);
|
|
12847
|
+
}
|
|
12848
|
+
}
|
|
12795
12849
|
}
|
|
12796
12850
|
else {
|
|
12797
12851
|
// verify-manual-login mode or no token: Show success but require manual login
|
|
@@ -12829,19 +12883,26 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
12829
12883
|
const response = await api.verifyMagicLink(token);
|
|
12830
12884
|
// Auto-login with magic link if token is provided
|
|
12831
12885
|
if (response.token) {
|
|
12832
|
-
//
|
|
12833
|
-
await
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
12837
|
-
// Clear the URL parameters
|
|
12886
|
+
// In proxy mode, wait for parent to acknowledge (validate & persist) before redirect
|
|
12887
|
+
// MUST await to ensure session is ready before any redirect
|
|
12888
|
+
await auth.login(response.token, response.user, response.accountData, true, getExpirationFromResponse(response), proxyMode // waitForParentAck
|
|
12889
|
+
);
|
|
12890
|
+
// Clean URL parameters regardless of redirect
|
|
12838
12891
|
const cleanUrl = window.location.href.split('?')[0];
|
|
12839
12892
|
window.history.replaceState({}, document.title, cleanUrl);
|
|
12840
|
-
// For magic link deep links, redirect immediately if configured
|
|
12841
|
-
// (user came from an email link, so redirect is expected behavior)
|
|
12842
12893
|
if (redirectUrl) {
|
|
12894
|
+
// Redirect to clean URL and resume flow
|
|
12895
|
+
log.log('Magic link verification complete, redirecting to:', redirectUrl);
|
|
12843
12896
|
performRedirect(redirectUrl, 'magic-link');
|
|
12844
12897
|
}
|
|
12898
|
+
else {
|
|
12899
|
+
// No redirect configured: show success UI
|
|
12900
|
+
setAuthSuccess(true);
|
|
12901
|
+
setSuccessMessage('Magic link verified! You are now logged in.');
|
|
12902
|
+
if (!proxyMode) {
|
|
12903
|
+
onAuthSuccess(response.token, response.user, response.accountData);
|
|
12904
|
+
}
|
|
12905
|
+
}
|
|
12845
12906
|
}
|
|
12846
12907
|
else {
|
|
12847
12908
|
throw new Error('Authentication failed - no token received');
|
|
@@ -13431,12 +13492,22 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
13431
13492
|
// Update auth context with account data if token is provided
|
|
13432
13493
|
if (response.token) {
|
|
13433
13494
|
// Phone auth can be login or signup - use isNewUser flag from backend if available
|
|
13434
|
-
//
|
|
13435
|
-
await auth.login(response.token, response.user, response.accountData, response.isNewUser, getExpirationFromResponse(response)
|
|
13436
|
-
|
|
13495
|
+
// In proxy mode, wait for parent to acknowledge (validate & persist) before redirect
|
|
13496
|
+
await auth.login(response.token, response.user, response.accountData, response.isNewUser, getExpirationFromResponse(response), proxyMode // waitForParentAck
|
|
13497
|
+
);
|
|
13437
13498
|
if (redirectUrl) {
|
|
13499
|
+
// Redirect to clean URL and resume flow
|
|
13500
|
+
log.log('Phone verification complete, redirecting to:', redirectUrl);
|
|
13438
13501
|
performRedirect(redirectUrl, 'phone-verified');
|
|
13439
13502
|
}
|
|
13503
|
+
else {
|
|
13504
|
+
// No redirect configured: show success UI
|
|
13505
|
+
setAuthSuccess(true);
|
|
13506
|
+
setSuccessMessage('Phone verified! You are now logged in.');
|
|
13507
|
+
if (!proxyMode) {
|
|
13508
|
+
onAuthSuccess(response.token, response.user, response.accountData);
|
|
13509
|
+
}
|
|
13510
|
+
}
|
|
13440
13511
|
}
|
|
13441
13512
|
else {
|
|
13442
13513
|
throw new Error('Authentication failed - no token received');
|