Skip to content

Commit eabee1a

Browse files
authored
Fix for authStateReady for FirebaseServerApp (#8085)
It turns out the FirebaseServerApp implementation in #8005 was not blocking auth initialization, so when testing end-to-end we were seeing race conditions with auth state. In this PR I address by awaiting the user fetch and moving the implementation into AuthImpl#initializeCurrentUser for cleanliness.
1 parent 003b3c7 commit eabee1a

File tree

2 files changed

+43
-39
lines changed

2 files changed

+43
-39
lines changed

packages/auth/src/core/auth/auth_impl.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ import { _logWarn } from '../util/log';
8181
import { _getPasswordPolicy } from '../../api/password_policy/get_password_policy';
8282
import { PasswordPolicyInternal } from '../../model/password_policy';
8383
import { PasswordPolicyImpl } from './password_policy_impl';
84+
import { getAccountInfo } from '../../api/account_management/account';
85+
import { UserImpl } from '../user/user_impl';
8486

8587
interface AsyncAction {
8688
(): Promise<void>;
@@ -174,10 +176,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
174176
}
175177
}
176178

177-
// Skip loading users from persistence in FirebaseServerApp Auth instances.
178-
if (!_isFirebaseServerApp(this.app)) {
179-
await this.initializeCurrentUser(popupRedirectResolver);
180-
}
179+
await this.initializeCurrentUser(popupRedirectResolver);
181180

182181
this.lastNotifiedUid = this.currentUser?.uid || null;
183182

@@ -221,9 +220,47 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
221220
await this._updateCurrentUser(user, /* skipBeforeStateCallbacks */ true);
222221
}
223222

223+
private async initializeCurrentUserFromIdToken(
224+
idToken: string
225+
): Promise<void> {
226+
try {
227+
const response = await getAccountInfo(this, { idToken });
228+
const user = await UserImpl._fromGetAccountInfoResponse(
229+
this,
230+
response,
231+
idToken
232+
);
233+
await this.directlySetCurrentUser(user);
234+
} catch (err) {
235+
console.warn(
236+
'FirebaseServerApp could not login user with provided authIdToken: ',
237+
err
238+
);
239+
await this.directlySetCurrentUser(null);
240+
}
241+
}
242+
224243
private async initializeCurrentUser(
225244
popupRedirectResolver?: PopupRedirectResolver
226245
): Promise<void> {
246+
if (_isFirebaseServerApp(this.app)) {
247+
const idToken = this.app.settings.authIdToken;
248+
if (idToken) {
249+
// Start the auth operation in the next tick to allow a moment for the customer's app to
250+
// attach an emulator, if desired.
251+
return new Promise<void>(resolve => {
252+
setTimeout(() =>
253+
this.initializeCurrentUserFromIdToken(idToken).then(
254+
resolve,
255+
resolve
256+
)
257+
);
258+
});
259+
} else {
260+
return this.directlySetCurrentUser(null);
261+
}
262+
}
263+
227264
// First check to see if we have a pending redirect event.
228265
const previouslyStoredUser =
229266
(await this.assertedPersistence.getCurrentUser()) as UserInternal | null;

packages/auth/src/core/auth/initialize.ts

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,15 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { _getProvider, _isFirebaseServerApp, FirebaseApp } from '@firebase/app';
18+
import { _getProvider, FirebaseApp } from '@firebase/app';
1919
import { deepEqual } from '@firebase/util';
2020
import { Auth, Dependencies } from '../../model/public_types';
2121

2222
import { AuthErrorCode } from '../errors';
2323
import { PersistenceInternal } from '../persistence';
2424
import { _fail } from '../util/assert';
2525
import { _getInstance } from '../util/instantiator';
26-
import { AuthImpl, _castAuth } from './auth_impl';
27-
import { UserImpl } from '../user/user_impl';
28-
import { getAccountInfo } from '../../api/account_management/account';
26+
import { AuthImpl } from './auth_impl';
2927

3028
/**
3129
* Initializes an {@link Auth} instance with fine-grained control over
@@ -67,40 +65,9 @@ export function initializeAuth(app: FirebaseApp, deps?: Dependencies): Auth {
6765

6866
const auth = provider.initialize({ options: deps }) as AuthImpl;
6967

70-
if (_isFirebaseServerApp(app)) {
71-
if (app.settings.authIdToken !== undefined) {
72-
const idToken = app.settings.authIdToken;
73-
// Start the auth operation in the next tick to allow a moment for the customer's app to
74-
// attach an emulator, if desired.
75-
setTimeout(() => void _loadUserFromIdToken(auth, idToken), 0);
76-
}
77-
}
78-
7968
return auth;
8069
}
8170

82-
export async function _loadUserFromIdToken(
83-
auth: Auth,
84-
idToken: string
85-
): Promise<void> {
86-
try {
87-
const response = await getAccountInfo(auth, { idToken });
88-
const authInternal = _castAuth(auth);
89-
await authInternal._initializationPromise;
90-
const user = await UserImpl._fromGetAccountInfoResponse(
91-
authInternal,
92-
response,
93-
idToken
94-
);
95-
await authInternal._updateCurrentUser(user);
96-
} catch (err) {
97-
console.warn(
98-
'FirebaseServerApp could not login user with provided authIdToken: ',
99-
err
100-
);
101-
}
102-
}
103-
10471
export function _initializeAuthInstance(
10572
auth: AuthImpl,
10673
deps?: Dependencies

0 commit comments

Comments
 (0)