Skip to content

Commit 202a114

Browse files
committed
more wip
1 parent 8554836 commit 202a114

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

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

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
7878
private redirectPersistenceManager?: PersistenceUserManager;
7979
private authStateSubscription = new Subscription<User>(this);
8080
private idTokenSubscription = new Subscription<User>(this);
81-
private beforeStateSubscription = new Subscription<User>(this);
81+
private beforeStateQueue: Array<(user: User | null) => Promise<void>> = [];
8282
private redirectUser: UserInternal | null = null;
8383
private isProactiveRefreshEnabled = false;
8484

@@ -325,14 +325,26 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
325325
AuthErrorCode.TENANT_ID_MISMATCH
326326
);
327327
}
328+
await this._runBeforeStateCallbacks(user);
328329

329330
return this.queue(async () => {
330331
await this.directlySetCurrentUser(user as UserInternal | null);
331332
this.notifyAuthListeners();
332333
});
333334
}
334335

336+
async _runBeforeStateCallbacks(user: User | null): Promise<void> {
337+
try {
338+
for (const beforeStateCallback of this.beforeStateQueue) {
339+
await beforeStateCallback(user);
340+
}
341+
} catch (e) {
342+
throw this._errorFactory.create(AuthErrorCode.LOGIN_BLOCKED, { message: e.message });
343+
}
344+
}
345+
335346
async signOut(): Promise<void> {
347+
await this._runBeforeStateCallbacks(null);
336348
// Clear the redirect user when signOut is called
337349
if (this.redirectPersistenceManager || this._popupRedirectResolver) {
338350
await this._setRedirectUser(null);
@@ -373,14 +385,29 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
373385
}
374386

375387
beforeAuthStateChanged(
376-
next: NextFn<User | null>,
388+
callback: (user: User | null) => void | Promise<void>
377389
): Unsubscribe {
378-
return this.registerStateListener(
379-
this.beforeStateSubscription,
380-
next,
381-
error,
382-
completed
383-
);
390+
// The callback could be sync or async. Wrap it into a
391+
// function that is always async.
392+
const wrappedCallback =
393+
(user: User | null): Promise<void> => new Promise((resolve, reject) => {
394+
try {
395+
const result = callback(user);
396+
// Either resolve with existing promise or wrap a non-promise
397+
// return value into a promise.
398+
resolve(result);
399+
} catch (e) {
400+
// Sync callback throws.
401+
reject(e);
402+
}
403+
});
404+
this.beforeStateQueue.push(wrappedCallback);
405+
const index = this.beforeStateQueue.length - 1;
406+
return () => {
407+
// Unsubscribe. Replace with no-op. Do not remove from array, or it will disturb
408+
// indexing of other elements.
409+
this.beforeStateQueue[index] = () => Promise.resolve();
410+
};
384411
}
385412

386413
onIdTokenChanged(
@@ -441,7 +468,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
441468
// Make sure we've cleared any pending persistence actions if we're not in
442469
// the initializer
443470
if (this._isInitialized) {
444-
await this.queue(async () => {});
471+
await this.queue(async () => { });
445472
}
446473

447474
if (this._currentUser?._redirectEventId === id) {
@@ -512,7 +539,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
512539
completed?: CompleteFn
513540
): Unsubscribe {
514541
if (this._deleted) {
515-
return () => {};
542+
return () => { };
516543
}
517544

518545
const cb =
@@ -620,7 +647,7 @@ class Subscription<T> {
620647
observer => (this.observer = observer)
621648
);
622649

623-
constructor(readonly auth: AuthInternal) {}
650+
constructor(readonly auth: AuthInternal) { }
624651

625652
get next(): NextFn<T | null> {
626653
_assert(this.observer, this.auth, AuthErrorCode.INTERNAL_ERROR);

packages/auth/src/core/errors.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export const enum AuthErrorCode {
7575
INVALID_SENDER = 'invalid-sender',
7676
INVALID_SESSION_INFO = 'invalid-verification-id',
7777
INVALID_TENANT_ID = 'invalid-tenant-id',
78+
LOGIN_BLOCKED = 'login-blocked',
7879
MFA_INFO_NOT_FOUND = 'multi-factor-info-not-found',
7980
MFA_REQUIRED = 'multi-factor-auth-required',
8081
MISSING_ANDROID_PACKAGE_NAME = 'missing-android-pkg-name',
@@ -245,6 +246,7 @@ function _debugErrorMap(): ErrorMap<AuthErrorCode> {
245246
'The verification ID used to create the phone auth credential is invalid.',
246247
[AuthErrorCode.INVALID_TENANT_ID]:
247248
"The Auth instance's tenant ID is invalid.",
249+
[AuthErrorCode.LOGIN_BLOCKED]: "Login blocked by user-provided method.",
248250
[AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME]:
249251
'An Android Package Name must be provided if the Android App is required to be installed.',
250252
[AuthErrorCode.MISSING_AUTH_DOMAIN]:
@@ -414,9 +416,10 @@ type GenericAuthErrorParams = {
414416
| AuthErrorCode.NO_AUTH_EVENT
415417
| AuthErrorCode.OPERATION_NOT_SUPPORTED
416418
>]: {
417-
appName: AppName;
419+
appName?: AppName;
418420
email?: string;
419421
phoneNumber?: string;
422+
message?: string;
420423
};
421424
};
422425

@@ -427,6 +430,7 @@ export interface AuthErrorParams extends GenericAuthErrorParams {
427430
[AuthErrorCode.ARGUMENT_ERROR]: { appName?: AppName };
428431
[AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH]: { appName?: AppName };
429432
[AuthErrorCode.INTERNAL_ERROR]: { appName?: AppName };
433+
[AuthErrorCode.LOGIN_BLOCKED]: { message?: string };
430434
[AuthErrorCode.OPERATION_NOT_SUPPORTED]: { appName?: AppName };
431435
[AuthErrorCode.NO_AUTH_EVENT]: { appName?: AppName };
432436
[AuthErrorCode.MFA_REQUIRED]: {

0 commit comments

Comments
 (0)