Skip to content

Commit 772604e

Browse files
committed
Fix: Pass iframe data on every call (#5053)
## Problem solved This removes any assumptions of the iframe's local storage persistence. <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on fixing the flaky authentication state in Progressive Web Apps (PWAs) by enhancing the `InAppWalletIframeCommunicator` and `IframeCommunicator` classes to properly manage local storage and client information. ### Detailed summary - Added `localStorage`, `clientId`, and `ecosystem` as parameters to `IFrameCommunicatorProps`. - Modified the constructor of `IframeCommunicator` to accept and assign `localStorage`, `clientId`, and `ecosystem`. - Updated `onIframeLoadedInitVariables` to retrieve authentication data from `localStorage`. - Enhanced message posting to include initialization data with every request to handle storage resets. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent 6e4cd21 commit 772604e

File tree

3 files changed

+44
-30
lines changed

3 files changed

+44
-30
lines changed

.changeset/tricky-lamps-cheer.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Fix flaky auth state in PWAs

packages/thirdweb/src/wallets/in-app/web/utils/iFrameCommunication/IframeCommunicator.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { sleep } from "../../../../../utils/sleep.js";
2+
import type { ClientScopedStorage } from "../../../../../wallets/in-app/core/authentication/client-scoped-storage.js";
3+
import type { Ecosystem } from "../../../../../wallets/in-app/core/wallet/types.js";
24

35
type IFrameCommunicatorProps = {
46
link: string;
57
baseUrl: string;
68
iframeId: string;
79
container?: HTMLElement;
810
onIframeInitialize?: () => void;
11+
localStorage: ClientScopedStorage;
12+
clientId: string;
13+
ecosystem?: Ecosystem;
914
};
1015

1116
const iframeBaseStyle = {
@@ -32,8 +37,11 @@ const isIframeLoaded = new Map<string, boolean>();
3237
export class IframeCommunicator<T extends { [key: string]: any }> {
3338
private iframe: HTMLIFrameElement;
3439
private POLLING_INTERVAL_SECONDS = 1.4;
35-
3640
private iframeBaseUrl;
41+
protected localStorage: ClientScopedStorage;
42+
protected clientId: string;
43+
protected ecosystem?: Ecosystem;
44+
3745
/**
3846
* @internal
3947
*/
@@ -43,7 +51,13 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
4351
iframeId,
4452
container = document.body,
4553
onIframeInitialize,
54+
localStorage,
55+
clientId,
56+
ecosystem,
4657
}: IFrameCommunicatorProps) {
58+
this.localStorage = localStorage;
59+
this.clientId = clientId;
60+
this.ecosystem = ecosystem;
4761
this.iframeBaseUrl = baseUrl;
4862

4963
// Creating the IFrame element for communication
@@ -89,7 +103,14 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
89103

90104
// biome-ignore lint/suspicious/noExplicitAny: TODO: fix later
91105
protected async onIframeLoadedInitVariables(): Promise<Record<string, any>> {
92-
return {};
106+
return {
107+
authCookie: await this.localStorage.getAuthCookie(),
108+
deviceShareStored: await this.localStorage.getDeviceShare(),
109+
walletUserId: await this.localStorage.getWalletUserId(),
110+
clientId: this.clientId,
111+
partnerId: this.ecosystem?.partnerId,
112+
ecosystemId: this.ecosystem?.id,
113+
};
93114
}
94115

95116
/**
@@ -118,13 +139,9 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
118139
};
119140
});
120141

121-
const INIT_IFRAME_EVENT = "initIframe";
122142
iframe?.contentWindow?.postMessage(
123-
// ? We initialise the iframe with a bunch
124-
// of useful information so that we don't have to pass it
125-
// through in each of the future call. This would be where we do it.
126143
{
127-
eventType: INIT_IFRAME_EVENT,
144+
eventType: "initIframe",
128145
data: await this.onIframeLoadedInitVariables(),
129146
},
130147
this.iframeBaseUrl,
@@ -176,7 +193,14 @@ export class IframeCommunicator<T extends { [key: string]: any }> {
176193
});
177194

178195
this.iframe.contentWindow?.postMessage(
179-
{ eventType: procedureName, data: params },
196+
{
197+
eventType: procedureName,
198+
// Pass the initialization data on every request in case the iframe storage was reset (can happen in some environments such as iOS PWAs)
199+
data: {
200+
...params,
201+
...(await this.onIframeLoadedInitVariables()),
202+
},
203+
},
180204
this.iframeBaseUrl,
181205
[channel.port2],
182206
);

packages/thirdweb/src/wallets/in-app/web/utils/iFrameCommunication/InAppWalletIframeCommunicator.ts

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ export class InAppWalletIframeCommunicator<
1111
// biome-ignore lint/suspicious/noExplicitAny: TODO: fix any
1212
T extends { [key: string]: any },
1313
> extends IframeCommunicator<T> {
14-
clientId: string;
15-
ecosystem?: Ecosystem;
1614
/**
1715
* @internal
1816
*/
@@ -35,30 +33,17 @@ export class InAppWalletIframeCommunicator<
3533
}).href,
3634
baseUrl,
3735
container: document.body,
36+
localStorage: new ClientScopedStorage({
37+
storage: webLocalStorage,
38+
clientId,
39+
ecosystem,
40+
}),
41+
clientId,
42+
ecosystem,
3843
});
3944
this.clientId = clientId;
4045
this.ecosystem = ecosystem;
4146
}
42-
43-
/**
44-
* @internal
45-
*/
46-
override async onIframeLoadedInitVariables() {
47-
const localStorage = new ClientScopedStorage({
48-
storage: webLocalStorage,
49-
clientId: this.clientId,
50-
ecosystem: this.ecosystem,
51-
});
52-
53-
return {
54-
authCookie: await localStorage.getAuthCookie(),
55-
deviceShareStored: await localStorage.getDeviceShare(),
56-
walletUserId: await localStorage.getWalletUserId(),
57-
clientId: this.clientId,
58-
partnerId: this.ecosystem?.partnerId,
59-
ecosystemId: this.ecosystem?.id,
60-
};
61-
}
6247
}
6348

6449
// This is the URL and ID tag of the iFrame that we communicate with

0 commit comments

Comments
 (0)