Skip to content

Commit 3f0fba4

Browse files
Wait for Auth to be initialized
1 parent b05b8e8 commit 3f0fba4

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

newIDE/app/src/Profile/AuthenticatedUserProvider.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ export default class AuthenticatedUserProvider extends React.Component<
152152
>(listUserCloudProjects);
153153

154154
async componentDidMount() {
155+
// Wait for Firebase to complete its initial auth check before doing anything.
156+
// This prevents a race condition where we check auth state before Firebase
157+
// has finished initializing, causing us to incorrectly think the user is logged out.
158+
await this.props.authentication.waitForInitialAuthCheck();
159+
155160
this._initializeAuthenticatedUser();
156161

157162
// Those callbacks are added a bit too late (after the authentication `hasAuthChanged` has already been triggered)
@@ -185,8 +190,9 @@ export default class AuthenticatedUserProvider extends React.Component<
185190
}
186191
});
187192

188-
// At startup, if the provider has mounted too late and the user is already logged in with Firebase,
189-
// we fetch the user profile.
193+
// At startup, check if the user is already logged in with Firebase.
194+
// Note: We can now safely check this synchronously because we've waited for
195+
// Firebase's initial auth check to complete above.
190196
if (this.props.authentication.getFirebaseUserSync()) {
191197
// The user is logged already: fetch its user profile (because the "user update"
192198
// won't trigger, as registered too late).

newIDE/app/src/Utils/GDevelopServices/Authentication.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,28 @@ export default class Authentication {
125125
_onUserLogoutCallbacks: Array<() => void | Promise<void>> = [];
126126
_onUserUpdateCallbacks: Array<() => void | Promise<void>> = [];
127127
loginProvider: ?LoginProvider;
128+
_initialAuthCheckPromise: Promise<void>;
128129

129130
constructor() {
130131
const app = initializeApp(GDevelopFirebaseConfig);
131132
this.auth = getAuth(app);
133+
134+
// Create a promise that resolves when Firebase completes its initial auth check.
135+
// This prevents race conditions where components check auth state before Firebase
136+
// has finished initializing.
137+
let resolveInitialCheck;
138+
this._initialAuthCheckPromise = new Promise(resolve => {
139+
resolveInitialCheck = resolve;
140+
});
141+
142+
let isFirstCall = true;
132143
onAuthStateChanged(this.auth, user => {
144+
if (isFirstCall) {
145+
// First call - Firebase has completed initial auth check
146+
isFirstCall = false;
147+
resolveInitialCheck();
148+
}
149+
133150
if (user) {
134151
// User has logged in or changed.
135152
this._onUserUpdateCallbacks.forEach(cb => cb());
@@ -530,4 +547,8 @@ export default class Authentication {
530547
isAuthenticated = (): boolean => {
531548
return !!this.auth.currentUser;
532549
};
550+
551+
waitForInitialAuthCheck = (): Promise<void> => {
552+
return this._initialAuthCheckPromise;
553+
};
533554
}

0 commit comments

Comments
 (0)