@firebase/auth 0.19.12 → 0.20.0

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.
Files changed (121) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/auth-public.d.ts +30 -0
  3. package/dist/auth.d.ts +38 -1
  4. package/dist/cordova/index.js +2 -2
  5. package/dist/cordova/internal/index.d.ts +1 -0
  6. package/dist/cordova/internal.js +3 -2
  7. package/dist/cordova/internal.js.map +1 -1
  8. package/dist/cordova/{popup_redirect-fd81f644.js → popup_redirect-1228b67a.js} +203 -43
  9. package/dist/cordova/popup_redirect-1228b67a.js.map +1 -0
  10. package/dist/cordova/src/core/auth/auth_impl.d.ts +3 -1
  11. package/dist/cordova/src/core/auth/middleware.d.ts +25 -0
  12. package/dist/cordova/src/core/auth/middleware.test.d.ts +17 -0
  13. package/dist/cordova/src/core/errors.d.ts +7 -1
  14. package/dist/cordova/src/core/index.d.ts +11 -0
  15. package/dist/cordova/src/core/strategies/redirect.d.ts +1 -0
  16. package/dist/cordova/src/model/popup_redirect.d.ts +2 -0
  17. package/dist/cordova/src/model/public_types.d.ts +10 -0
  18. package/dist/cordova/test/integration/flows/middleware_test_generator.d.ts +18 -0
  19. package/dist/cordova/test/integration/webdriver/util/functions.d.ts +4 -0
  20. package/dist/esm2017/{index-7078a255.js → index-815f1b87.js} +143 -18
  21. package/dist/esm2017/index-815f1b87.js.map +1 -0
  22. package/dist/esm2017/index.js +1 -1
  23. package/dist/esm2017/internal/index.d.ts +1 -0
  24. package/dist/esm2017/internal.js +3 -2
  25. package/dist/esm2017/internal.js.map +1 -1
  26. package/dist/esm2017/src/core/auth/auth_impl.d.ts +3 -1
  27. package/dist/esm2017/src/core/auth/middleware.d.ts +25 -0
  28. package/dist/esm2017/src/core/auth/middleware.test.d.ts +17 -0
  29. package/dist/esm2017/src/core/errors.d.ts +7 -1
  30. package/dist/esm2017/src/core/index.d.ts +11 -0
  31. package/dist/esm2017/src/core/strategies/redirect.d.ts +1 -0
  32. package/dist/esm2017/src/model/popup_redirect.d.ts +2 -0
  33. package/dist/esm2017/src/model/public_types.d.ts +10 -0
  34. package/dist/esm2017/test/integration/flows/middleware_test_generator.d.ts +18 -0
  35. package/dist/esm2017/test/integration/webdriver/util/functions.d.ts +4 -0
  36. package/dist/esm5/{index-7a476dcd.js → index-dc27d95e.js} +203 -43
  37. package/dist/esm5/index-dc27d95e.js.map +1 -0
  38. package/dist/esm5/index.js +1 -1
  39. package/dist/esm5/internal/index.d.ts +1 -0
  40. package/dist/esm5/internal.js +3 -2
  41. package/dist/esm5/internal.js.map +1 -1
  42. package/dist/esm5/src/core/auth/auth_impl.d.ts +3 -1
  43. package/dist/esm5/src/core/auth/middleware.d.ts +25 -0
  44. package/dist/esm5/src/core/auth/middleware.test.d.ts +17 -0
  45. package/dist/esm5/src/core/errors.d.ts +7 -1
  46. package/dist/esm5/src/core/index.d.ts +11 -0
  47. package/dist/esm5/src/core/strategies/redirect.d.ts +1 -0
  48. package/dist/esm5/src/model/popup_redirect.d.ts +2 -0
  49. package/dist/esm5/src/model/public_types.d.ts +10 -0
  50. package/dist/esm5/test/integration/flows/middleware_test_generator.d.ts +18 -0
  51. package/dist/esm5/test/integration/webdriver/util/functions.d.ts +4 -0
  52. package/dist/index.webworker.esm5.js +198 -42
  53. package/dist/index.webworker.esm5.js.map +1 -1
  54. package/dist/internal/index.d.ts +1 -0
  55. package/dist/node/{index-eabd3e6c.js → index-ec34877a.js} +199 -42
  56. package/dist/node/index-ec34877a.js.map +1 -0
  57. package/dist/node/index.js +2 -1
  58. package/dist/node/index.js.map +1 -1
  59. package/dist/node/internal/index.d.ts +1 -0
  60. package/dist/node/internal.js +7 -1
  61. package/dist/node/internal.js.map +1 -1
  62. package/dist/node/src/core/auth/auth_impl.d.ts +3 -1
  63. package/dist/node/src/core/auth/middleware.d.ts +25 -0
  64. package/dist/node/src/core/auth/middleware.test.d.ts +17 -0
  65. package/dist/node/src/core/errors.d.ts +7 -1
  66. package/dist/node/src/core/index.d.ts +11 -0
  67. package/dist/node/src/core/strategies/redirect.d.ts +1 -0
  68. package/dist/node/src/model/popup_redirect.d.ts +2 -0
  69. package/dist/node/src/model/public_types.d.ts +10 -0
  70. package/dist/node/test/integration/flows/middleware_test_generator.d.ts +18 -0
  71. package/dist/node/test/integration/webdriver/util/functions.d.ts +4 -0
  72. package/dist/node-esm/{index-d709908a.js → index-c85cf380.js} +139 -18
  73. package/dist/node-esm/index-c85cf380.js.map +1 -0
  74. package/dist/node-esm/index.js +1 -1
  75. package/dist/node-esm/internal/index.d.ts +1 -0
  76. package/dist/node-esm/internal.js +7 -3
  77. package/dist/node-esm/internal.js.map +1 -1
  78. package/dist/node-esm/src/core/auth/auth_impl.d.ts +3 -1
  79. package/dist/node-esm/src/core/auth/middleware.d.ts +25 -0
  80. package/dist/node-esm/src/core/auth/middleware.test.d.ts +17 -0
  81. package/dist/node-esm/src/core/errors.d.ts +7 -1
  82. package/dist/node-esm/src/core/index.d.ts +11 -0
  83. package/dist/node-esm/src/core/strategies/redirect.d.ts +1 -0
  84. package/dist/node-esm/src/model/popup_redirect.d.ts +2 -0
  85. package/dist/node-esm/src/model/public_types.d.ts +10 -0
  86. package/dist/node-esm/test/integration/flows/middleware_test_generator.d.ts +18 -0
  87. package/dist/node-esm/test/integration/webdriver/util/functions.d.ts +4 -0
  88. package/dist/rn/index.js +2 -1
  89. package/dist/rn/index.js.map +1 -1
  90. package/dist/rn/internal/index.d.ts +1 -0
  91. package/dist/rn/internal.js +8 -1
  92. package/dist/rn/internal.js.map +1 -1
  93. package/dist/rn/{phone-eec7f987.js → phone-ae029e3c.js} +199 -42
  94. package/dist/rn/phone-ae029e3c.js.map +1 -0
  95. package/dist/rn/src/core/auth/auth_impl.d.ts +3 -1
  96. package/dist/rn/src/core/auth/middleware.d.ts +25 -0
  97. package/dist/rn/src/core/auth/middleware.test.d.ts +17 -0
  98. package/dist/rn/src/core/errors.d.ts +7 -1
  99. package/dist/rn/src/core/index.d.ts +11 -0
  100. package/dist/rn/src/core/strategies/redirect.d.ts +1 -0
  101. package/dist/rn/src/model/popup_redirect.d.ts +2 -0
  102. package/dist/rn/src/model/public_types.d.ts +10 -0
  103. package/dist/rn/test/integration/flows/middleware_test_generator.d.ts +18 -0
  104. package/dist/rn/test/integration/webdriver/util/functions.d.ts +4 -0
  105. package/dist/src/core/auth/auth_impl.d.ts +3 -1
  106. package/dist/src/core/auth/middleware.d.ts +25 -0
  107. package/dist/src/core/auth/middleware.test.d.ts +17 -0
  108. package/dist/src/core/errors.d.ts +7 -1
  109. package/dist/src/core/index.d.ts +11 -0
  110. package/dist/src/core/strategies/redirect.d.ts +1 -0
  111. package/dist/src/model/popup_redirect.d.ts +2 -0
  112. package/dist/src/model/public_types.d.ts +10 -0
  113. package/dist/test/integration/flows/middleware_test_generator.d.ts +18 -0
  114. package/dist/test/integration/webdriver/util/functions.d.ts +4 -0
  115. package/package.json +6 -6
  116. package/dist/cordova/popup_redirect-fd81f644.js.map +0 -1
  117. package/dist/esm2017/index-7078a255.js.map +0 -1
  118. package/dist/esm5/index-7a476dcd.js.map +0 -1
  119. package/dist/node/index-eabd3e6c.js.map +0 -1
  120. package/dist/node-esm/index-d709908a.js.map +0 -1
  121. package/dist/rn/phone-eec7f987.js.map +0 -1
@@ -39,6 +39,7 @@ export declare class AuthImpl implements AuthInternal, _FirebaseService {
39
39
  private redirectPersistenceManager?;
40
40
  private authStateSubscription;
41
41
  private idTokenSubscription;
42
+ private readonly beforeStateQueue;
42
43
  private redirectUser;
43
44
  private isProactiveRefreshEnabled;
44
45
  _canInitEmulator: boolean;
@@ -64,12 +65,13 @@ export declare class AuthImpl implements AuthInternal, _FirebaseService {
64
65
  useDeviceLanguage(): void;
65
66
  _delete(): Promise<void>;
66
67
  updateCurrentUser(userExtern: User | null): Promise<void>;
67
- _updateCurrentUser(user: User | null): Promise<void>;
68
+ _updateCurrentUser(user: User | null, skipBeforeStateCallbacks?: boolean): Promise<void>;
68
69
  signOut(): Promise<void>;
69
70
  setPersistence(persistence: Persistence): Promise<void>;
70
71
  _getPersistence(): string;
71
72
  _updateErrorMap(errorMap: AuthErrorMap): void;
72
73
  onAuthStateChanged(nextOrObserver: NextOrObserver<User>, error?: ErrorFn, completed?: CompleteFn): Unsubscribe;
74
+ beforeAuthStateChanged(callback: (user: User | null) => void | Promise<void>, onAbort?: () => void): Unsubscribe;
73
75
  onIdTokenChanged(nextOrObserver: NextOrObserver<User>, error?: ErrorFn, completed?: CompleteFn): Unsubscribe;
74
76
  toJSON(): object;
75
77
  _setRedirectUser(user: UserInternal | null, popupRedirectResolver?: PopupRedirectResolver): Promise<void>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { AuthInternal } from '../../model/auth';
18
+ import { Unsubscribe, User } from '../../model/public_types';
19
+ export declare class AuthMiddlewareQueue {
20
+ private readonly auth;
21
+ private readonly queue;
22
+ constructor(auth: AuthInternal);
23
+ pushCallback(callback: (user: User | null) => void | Promise<void>, onAbort?: () => void): Unsubscribe;
24
+ runMiddleware(nextUser: User | null): Promise<void>;
25
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ export {};
@@ -72,6 +72,7 @@ export declare const enum AuthErrorCode {
72
72
  INVALID_SENDER = "invalid-sender",
73
73
  INVALID_SESSION_INFO = "invalid-verification-id",
74
74
  INVALID_TENANT_ID = "invalid-tenant-id",
75
+ LOGIN_BLOCKED = "login-blocked",
75
76
  MFA_INFO_NOT_FOUND = "multi-factor-info-not-found",
76
77
  MFA_REQUIRED = "multi-factor-auth-required",
77
78
  MISSING_ANDROID_PACKAGE_NAME = "missing-android-pkg-name",
@@ -154,9 +155,10 @@ export interface NamedErrorParams {
154
155
  */
155
156
  declare type GenericAuthErrorParams = {
156
157
  [key in Exclude<AuthErrorCode, AuthErrorCode.ARGUMENT_ERROR | AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH | AuthErrorCode.INTERNAL_ERROR | AuthErrorCode.MFA_REQUIRED | AuthErrorCode.NO_AUTH_EVENT | AuthErrorCode.OPERATION_NOT_SUPPORTED>]: {
157
- appName: AppName;
158
+ appName?: AppName;
158
159
  email?: string;
159
160
  phoneNumber?: string;
161
+ message?: string;
160
162
  };
161
163
  };
162
164
  /**
@@ -172,6 +174,10 @@ export interface AuthErrorParams extends GenericAuthErrorParams {
172
174
  [AuthErrorCode.INTERNAL_ERROR]: {
173
175
  appName?: AppName;
174
176
  };
177
+ [AuthErrorCode.LOGIN_BLOCKED]: {
178
+ appName?: AppName;
179
+ originalMessage?: string;
180
+ };
175
181
  [AuthErrorCode.OPERATION_NOT_SUPPORTED]: {
176
182
  appName?: AppName;
177
183
  };
@@ -50,6 +50,17 @@ export declare function setPersistence(auth: Auth, persistence: Persistence): Pr
50
50
  * @public
51
51
  */
52
52
  export declare function onIdTokenChanged(auth: Auth, nextOrObserver: NextOrObserver<User>, error?: ErrorFn, completed?: CompleteFn): Unsubscribe;
53
+ /**
54
+ * Adds a blocking callback that runs before an auth state change
55
+ * sets a new user.
56
+ *
57
+ * @param auth - The {@link Auth} instance.
58
+ * @param callback - callback triggered before new user value is set.
59
+ * If this throws, it blocks the user from being set.
60
+ * @param onAbort - callback triggered if a later `beforeAuthStateChanged()`
61
+ * callback throws, allowing you to undo any side effects.
62
+ */
63
+ export declare function beforeAuthStateChanged(auth: Auth, callback: (user: User | null) => void | Promise<void>, onAbort?: () => void): Unsubscribe;
53
64
  /**
54
65
  * Adds an observer for changes to the user's sign-in state.
55
66
  *
@@ -33,3 +33,4 @@ export declare class RedirectAction extends AbstractPopupRedirectOperation {
33
33
  export declare function _getAndClearPendingRedirectStatus(resolver: PopupRedirectResolverInternal, auth: AuthInternal): Promise<boolean>;
34
34
  export declare function _setPendingRedirectStatus(resolver: PopupRedirectResolverInternal, auth: AuthInternal): Promise<void>;
35
35
  export declare function _clearRedirectOutcomes(): void;
36
+ export declare function _overrideRedirectResult(auth: AuthInternal, result: () => Promise<UserCredentialInternal | null>): void;
@@ -18,6 +18,7 @@ import { Auth, AuthProvider, Persistence, PopupRedirectResolver, UserCredential
18
18
  import { FirebaseError } from '@firebase/util';
19
19
  import { AuthPopup } from '../platform_browser/util/popup';
20
20
  import { AuthInternal } from './auth';
21
+ import { UserCredentialInternal } from './user';
21
22
  export declare const enum EventFilter {
22
23
  POPUP = 0,
23
24
  REDIRECT = 1
@@ -89,4 +90,5 @@ export interface PopupRedirectResolverInternal extends PopupRedirectResolver {
89
90
  _redirectPersistence: Persistence;
90
91
  _originValidation(auth: Auth): Promise<void>;
91
92
  _completeRedirectFn: (auth: Auth, resolver: PopupRedirectResolver, bypassAuthState: boolean) => Promise<UserCredential | null>;
93
+ _overrideRedirectResult: (auth: AuthInternal, resultGetter: () => Promise<UserCredentialInternal | null>) => void;
92
94
  }
@@ -228,6 +228,16 @@ export interface Auth {
228
228
  * @param completed - callback triggered when observer is removed.
229
229
  */
230
230
  onAuthStateChanged(nextOrObserver: NextOrObserver<User | null>, error?: ErrorFn, completed?: CompleteFn): Unsubscribe;
231
+ /**
232
+ * Adds a blocking callback that runs before an auth state change
233
+ * sets a new user.
234
+ *
235
+ * @param callback - callback triggered before new user value is set.
236
+ * If this throws, it blocks the user from being set.
237
+ * @param onAbort - callback triggered if a later `beforeAuthStateChanged()`
238
+ * callback throws, allowing you to undo any side effects.
239
+ */
240
+ beforeAuthStateChanged(callback: (user: User | null) => void | Promise<void>, onAbort?: () => void): Unsubscribe;
231
241
  /**
232
242
  * Adds an observer for changes to the signed-in user's ID token.
233
243
  *
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { Auth } from '@firebase/auth';
18
+ export declare function generateMiddlewareTests(authGetter: () => Auth, signIn: () => Promise<unknown>): void;
@@ -70,6 +70,10 @@ export declare enum PersistenceFunction {
70
70
  SET_PERSISTENCE_INDEXED_DB = "persistence.setPersistenceIndexedDB",
71
71
  SET_PERSISTENCE_LOCAL_STORAGE = "persistence.setPersistenceLocalStorage"
72
72
  }
73
+ export declare enum MiddlewareFunction {
74
+ ATTACH_BLOCKING_MIDDLEWARE = "middleware.attachBlockingMiddleware",
75
+ ATTACH_BLOCKING_MIDDLEWARE_ON_START = "middleware.attachBlockingMiddlewareOnStart"
76
+ }
73
77
  /** Available firebase UI functions (only for compat tests) */
74
78
  export declare enum UiFunction {
75
79
  LOAD = "ui.loadUiCode",
@@ -198,6 +198,7 @@ function _debugErrorMap() {
198
198
  'Please fix by going to the Auth email templates section in the Firebase Console.',
199
199
  ["invalid-verification-id" /* INVALID_SESSION_INFO */]: 'The verification ID used to create the phone auth credential is invalid.',
200
200
  ["invalid-tenant-id" /* INVALID_TENANT_ID */]: "The Auth instance's tenant ID is invalid.",
201
+ ["login-blocked" /* LOGIN_BLOCKED */]: "Login blocked by user-provided method: {$originalMessage}",
201
202
  ["missing-android-pkg-name" /* MISSING_ANDROID_PACKAGE_NAME */]: 'An Android Package Name must be provided if the Android App is required to be installed.',
202
203
  ["auth-domain-config-required" /* MISSING_AUTH_DOMAIN */]: 'Be sure to include authDomain when calling firebase.initializeApp(), ' +
203
204
  'by following the instructions in the Firebase console.',
@@ -2116,6 +2117,83 @@ function _getClientVersion(clientPlatform, frameworks = []) {
2116
2117
  return `${reportedPlatform}/${"JsCore" /* CORE */}/${SDK_VERSION}/${reportedFrameworks}`;
2117
2118
  }
2118
2119
 
2120
+ /**
2121
+ * @license
2122
+ * Copyright 2022 Google LLC
2123
+ *
2124
+ * Licensed under the Apache License, Version 2.0 (the "License");
2125
+ * you may not use this file except in compliance with the License.
2126
+ * You may obtain a copy of the License at
2127
+ *
2128
+ * http://www.apache.org/licenses/LICENSE-2.0
2129
+ *
2130
+ * Unless required by applicable law or agreed to in writing, software
2131
+ * distributed under the License is distributed on an "AS IS" BASIS,
2132
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2133
+ * See the License for the specific language governing permissions and
2134
+ * limitations under the License.
2135
+ */
2136
+ class AuthMiddlewareQueue {
2137
+ constructor(auth) {
2138
+ this.auth = auth;
2139
+ this.queue = [];
2140
+ }
2141
+ pushCallback(callback, onAbort) {
2142
+ // The callback could be sync or async. Wrap it into a
2143
+ // function that is always async.
2144
+ const wrappedCallback = (user) => new Promise((resolve, reject) => {
2145
+ try {
2146
+ const result = callback(user);
2147
+ // Either resolve with existing promise or wrap a non-promise
2148
+ // return value into a promise.
2149
+ resolve(result);
2150
+ }
2151
+ catch (e) {
2152
+ // Sync callback throws.
2153
+ reject(e);
2154
+ }
2155
+ });
2156
+ // Attach the onAbort if present
2157
+ wrappedCallback.onAbort = onAbort;
2158
+ this.queue.push(wrappedCallback);
2159
+ const index = this.queue.length - 1;
2160
+ return () => {
2161
+ // Unsubscribe. Replace with no-op. Do not remove from array, or it will disturb
2162
+ // indexing of other elements.
2163
+ this.queue[index] = () => Promise.resolve();
2164
+ };
2165
+ }
2166
+ async runMiddleware(nextUser) {
2167
+ if (this.auth.currentUser === nextUser) {
2168
+ return;
2169
+ }
2170
+ // While running the middleware, build a temporary stack of onAbort
2171
+ // callbacks to call if one middleware callback rejects.
2172
+ const onAbortStack = [];
2173
+ try {
2174
+ for (const beforeStateCallback of this.queue) {
2175
+ await beforeStateCallback(nextUser);
2176
+ // Only push the onAbort if the callback succeeds
2177
+ if (beforeStateCallback.onAbort) {
2178
+ onAbortStack.push(beforeStateCallback.onAbort);
2179
+ }
2180
+ }
2181
+ }
2182
+ catch (e) {
2183
+ // Run all onAbort, with separate try/catch to ignore any errors and
2184
+ // continue
2185
+ onAbortStack.reverse();
2186
+ for (const onAbort of onAbortStack) {
2187
+ try {
2188
+ onAbort();
2189
+ }
2190
+ catch (_) { /* swallow error */ }
2191
+ }
2192
+ throw this.auth._errorFactory.create("login-blocked" /* LOGIN_BLOCKED */, { originalMessage: e.message });
2193
+ }
2194
+ }
2195
+ }
2196
+
2119
2197
  /**
2120
2198
  * @license
2121
2199
  * Copyright 2020 Google LLC
@@ -2142,6 +2220,7 @@ class AuthImpl {
2142
2220
  this.operations = Promise.resolve();
2143
2221
  this.authStateSubscription = new Subscription(this);
2144
2222
  this.idTokenSubscription = new Subscription(this);
2223
+ this.beforeStateQueue = new AuthMiddlewareQueue(this);
2145
2224
  this.redirectUser = null;
2146
2225
  this.isProactiveRefreshEnabled = false;
2147
2226
  // Any network calls will set this to true and prevent subsequent emulator
@@ -2218,16 +2297,19 @@ class AuthImpl {
2218
2297
  return;
2219
2298
  }
2220
2299
  // Update current Auth state. Either a new login or logout.
2221
- await this._updateCurrentUser(user);
2300
+ // Skip blocking callbacks, they should not apply to a change in another tab.
2301
+ await this._updateCurrentUser(user, /* skipBeforeStateCallbacks */ true);
2222
2302
  }
2223
2303
  async initializeCurrentUser(popupRedirectResolver) {
2224
2304
  var _a;
2225
2305
  // First check to see if we have a pending redirect event.
2226
- let storedUser = (await this.assertedPersistence.getCurrentUser());
2306
+ const previouslyStoredUser = (await this.assertedPersistence.getCurrentUser());
2307
+ let futureCurrentUser = previouslyStoredUser;
2308
+ let needsTocheckMiddleware = false;
2227
2309
  if (popupRedirectResolver && this.config.authDomain) {
2228
2310
  await this.getOrInitRedirectPersistenceManager();
2229
2311
  const redirectUserEventId = (_a = this.redirectUser) === null || _a === void 0 ? void 0 : _a._redirectEventId;
2230
- const storedUserEventId = storedUser === null || storedUser === void 0 ? void 0 : storedUser._redirectEventId;
2312
+ const storedUserEventId = futureCurrentUser === null || futureCurrentUser === void 0 ? void 0 : futureCurrentUser._redirectEventId;
2231
2313
  const result = await this.tryRedirectSignIn(popupRedirectResolver);
2232
2314
  // If the stored user (i.e. the old "currentUser") has a redirectId that
2233
2315
  // matches the redirect user, then we want to initially sign in with the
@@ -2235,18 +2317,34 @@ class AuthImpl {
2235
2317
  // TODO(samgho): More thoroughly test all of this
2236
2318
  if ((!redirectUserEventId || redirectUserEventId === storedUserEventId) &&
2237
2319
  (result === null || result === void 0 ? void 0 : result.user)) {
2238
- storedUser = result.user;
2320
+ futureCurrentUser = result.user;
2321
+ needsTocheckMiddleware = true;
2239
2322
  }
2240
2323
  }
2241
2324
  // If no user in persistence, there is no current user. Set to null.
2242
- if (!storedUser) {
2325
+ if (!futureCurrentUser) {
2243
2326
  return this.directlySetCurrentUser(null);
2244
2327
  }
2245
- if (!storedUser._redirectEventId) {
2246
- // This isn't a redirect user, we can reload and bail
2247
- // This will also catch the redirected user, if available, as that method
2248
- // strips the _redirectEventId
2249
- return this.reloadAndSetCurrentUserOrClear(storedUser);
2328
+ if (!futureCurrentUser._redirectEventId) {
2329
+ // This isn't a redirect link operation, we can reload and bail.
2330
+ // First though, ensure that we check the middleware is happy.
2331
+ if (needsTocheckMiddleware) {
2332
+ try {
2333
+ await this.beforeStateQueue.runMiddleware(futureCurrentUser);
2334
+ }
2335
+ catch (e) {
2336
+ futureCurrentUser = previouslyStoredUser;
2337
+ // We know this is available since the bit is only set when the
2338
+ // resolver is available
2339
+ this._popupRedirectResolver._overrideRedirectResult(this, () => Promise.reject(e));
2340
+ }
2341
+ }
2342
+ if (futureCurrentUser) {
2343
+ return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
2344
+ }
2345
+ else {
2346
+ return this.directlySetCurrentUser(null);
2347
+ }
2250
2348
  }
2251
2349
  _assert(this._popupRedirectResolver, this, "argument-error" /* ARGUMENT_ERROR */);
2252
2350
  await this.getOrInitRedirectPersistenceManager();
@@ -2254,10 +2352,10 @@ class AuthImpl {
2254
2352
  // DO NOT reload the current user, otherwise they'll be cleared from storage.
2255
2353
  // This is important for the reauthenticateWithRedirect() flow.
2256
2354
  if (this.redirectUser &&
2257
- this.redirectUser._redirectEventId === storedUser._redirectEventId) {
2258
- return this.directlySetCurrentUser(storedUser);
2355
+ this.redirectUser._redirectEventId === futureCurrentUser._redirectEventId) {
2356
+ return this.directlySetCurrentUser(futureCurrentUser);
2259
2357
  }
2260
- return this.reloadAndSetCurrentUserOrClear(storedUser);
2358
+ return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
2261
2359
  }
2262
2360
  async tryRedirectSignIn(redirectResolver) {
2263
2361
  // The redirect user needs to be checked (and signed in if available)
@@ -2318,24 +2416,31 @@ class AuthImpl {
2318
2416
  }
2319
2417
  return this._updateCurrentUser(user && user._clone(this));
2320
2418
  }
2321
- async _updateCurrentUser(user) {
2419
+ async _updateCurrentUser(user, skipBeforeStateCallbacks = false) {
2322
2420
  if (this._deleted) {
2323
2421
  return;
2324
2422
  }
2325
2423
  if (user) {
2326
2424
  _assert(this.tenantId === user.tenantId, this, "tenant-id-mismatch" /* TENANT_ID_MISMATCH */);
2327
2425
  }
2426
+ if (!skipBeforeStateCallbacks) {
2427
+ await this.beforeStateQueue.runMiddleware(user);
2428
+ }
2328
2429
  return this.queue(async () => {
2329
2430
  await this.directlySetCurrentUser(user);
2330
2431
  this.notifyAuthListeners();
2331
2432
  });
2332
2433
  }
2333
2434
  async signOut() {
2435
+ // Run first, to block _setRedirectUser() if any callbacks fail.
2436
+ await this.beforeStateQueue.runMiddleware(null);
2334
2437
  // Clear the redirect user when signOut is called
2335
2438
  if (this.redirectPersistenceManager || this._popupRedirectResolver) {
2336
2439
  await this._setRedirectUser(null);
2337
2440
  }
2338
- return this._updateCurrentUser(null);
2441
+ // Prevent callbacks from being called again in _updateCurrentUser, as
2442
+ // they were already called in the first line.
2443
+ return this._updateCurrentUser(null, /* skipBeforeStateCallbacks */ true);
2339
2444
  }
2340
2445
  setPersistence(persistence) {
2341
2446
  return this.queue(async () => {
@@ -2351,6 +2456,9 @@ class AuthImpl {
2351
2456
  onAuthStateChanged(nextOrObserver, error, completed) {
2352
2457
  return this.registerStateListener(this.authStateSubscription, nextOrObserver, error, completed);
2353
2458
  }
2459
+ beforeAuthStateChanged(callback, onAbort) {
2460
+ return this.beforeStateQueue.pushCallback(callback, onAbort);
2461
+ }
2354
2462
  onIdTokenChanged(nextOrObserver, error, completed) {
2355
2463
  return this.registerStateListener(this.idTokenSubscription, nextOrObserver, error, completed);
2356
2464
  }
@@ -5559,6 +5667,19 @@ function setPersistence(auth, persistence) {
5559
5667
  function onIdTokenChanged(auth, nextOrObserver, error, completed) {
5560
5668
  return getModularInstance(auth).onIdTokenChanged(nextOrObserver, error, completed);
5561
5669
  }
5670
+ /**
5671
+ * Adds a blocking callback that runs before an auth state change
5672
+ * sets a new user.
5673
+ *
5674
+ * @param auth - The {@link Auth} instance.
5675
+ * @param callback - callback triggered before new user value is set.
5676
+ * If this throws, it blocks the user from being set.
5677
+ * @param onAbort - callback triggered if a later `beforeAuthStateChanged()`
5678
+ * callback throws, allowing you to undo any side effects.
5679
+ */
5680
+ function beforeAuthStateChanged(auth, callback, onAbort) {
5681
+ return getModularInstance(auth).beforeAuthStateChanged(callback, onAbort);
5682
+ }
5562
5683
  /**
5563
5684
  * Adds an observer for changes to the user's sign-in state.
5564
5685
  *
@@ -8189,6 +8310,9 @@ async function _setPendingRedirectStatus(resolver, auth) {
8189
8310
  function _clearRedirectOutcomes() {
8190
8311
  redirectOutcomeMap.clear();
8191
8312
  }
8313
+ function _overrideRedirectResult(auth, result) {
8314
+ redirectOutcomeMap.set(auth._key(), result);
8315
+ }
8192
8316
  function resolverPersistence(resolver) {
8193
8317
  return _getInstance(resolver._redirectPersistence);
8194
8318
  }
@@ -8993,6 +9117,7 @@ class BrowserPopupRedirectResolver {
8993
9117
  this.originValidationPromises = {};
8994
9118
  this._redirectPersistence = browserSessionPersistence;
8995
9119
  this._completeRedirectFn = _getRedirectResult;
9120
+ this._overrideRedirectResult = _overrideRedirectResult;
8996
9121
  }
8997
9122
  // Wrapping in async even though we don't await anywhere in order
8998
9123
  // to make sure errors are raised as promise rejections
@@ -9142,7 +9267,7 @@ class PhoneMultiFactorGenerator {
9142
9267
  PhoneMultiFactorGenerator.FACTOR_ID = 'phone';
9143
9268
 
9144
9269
  var name = "@firebase/auth";
9145
- var version = "0.19.12";
9270
+ var version = "0.20.0";
9146
9271
 
9147
9272
  /**
9148
9273
  * @license
@@ -9332,5 +9457,5 @@ function getAuth(app = getApp()) {
9332
9457
  }
9333
9458
  registerAuth("Browser" /* BROWSER */);
9334
9459
 
9335
- export { sendPasswordResetEmail as $, ActionCodeOperation as A, prodErrorMap as B, AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY as C, initializeAuth as D, connectAuthEmulator as E, FactorId as F, AuthCredential as G, EmailAuthCredential as H, OAuthCredential as I, PhoneAuthCredential as J, inMemoryPersistence as K, EmailAuthProvider as L, FacebookAuthProvider as M, GoogleAuthProvider as N, OperationType as O, PhoneAuthProvider as P, GithubAuthProvider as Q, RecaptchaVerifier as R, SignInMethod as S, OAuthProvider as T, SAMLAuthProvider as U, TwitterAuthProvider as V, signInAnonymously as W, signInWithCredential as X, linkWithCredential as Y, reauthenticateWithCredential as Z, signInWithCustomToken as _, browserSessionPersistence as a, confirmPasswordReset as a0, applyActionCode as a1, checkActionCode as a2, verifyPasswordResetCode as a3, createUserWithEmailAndPassword as a4, signInWithEmailAndPassword as a5, sendSignInLinkToEmail as a6, isSignInWithEmailLink as a7, signInWithEmailLink as a8, fetchSignInMethodsForEmail as a9, _getRedirectResult as aA, _clearRedirectOutcomes as aB, _castAuth as aC, UserImpl as aD, AuthImpl as aE, _getClientVersion as aF, _generateEventId as aG, AuthPopup as aH, FetchProvider as aI, SAMLAuthCredential as aJ, sendEmailVerification as aa, verifyBeforeUpdateEmail as ab, ActionCodeURL as ac, parseActionCodeURL as ad, updateProfile as ae, updateEmail as af, updatePassword as ag, getIdToken as ah, getIdTokenResult as ai, unlink as aj, getAdditionalUserInfo as ak, reload as al, getMultiFactorResolver as am, multiFactor as an, _isIOS7Or8 as ao, debugAssert as ap, _isIOS as aq, _isAndroid as ar, _fail as as, _getRedirectUrl as at, _getProjectConfig as au, _createError as av, _assert as aw, _getInstance as ax, _persistenceKeyName as ay, AuthEventManager as az, browserLocalPersistence as b, signInWithPopup as c, linkWithPopup as d, reauthenticateWithPopup as e, signInWithRedirect as f, linkWithRedirect as g, reauthenticateWithRedirect as h, indexedDBLocalPersistence as i, getRedirectResult as j, browserPopupRedirectResolver as k, linkWithPhoneNumber as l, PhoneMultiFactorGenerator as m, getAuth as n, ProviderId as o, setPersistence as p, onIdTokenChanged as q, reauthenticateWithPhoneNumber as r, signInWithPhoneNumber as s, onAuthStateChanged as t, updatePhoneNumber as u, useDeviceLanguage as v, updateCurrentUser as w, signOut as x, deleteUser as y, debugErrorMap as z };
9336
- //# sourceMappingURL=index-7078a255.js.map
9460
+ export { signInWithCustomToken as $, ActionCodeOperation as A, debugErrorMap as B, prodErrorMap as C, AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY as D, initializeAuth as E, FactorId as F, connectAuthEmulator as G, AuthCredential as H, EmailAuthCredential as I, OAuthCredential as J, PhoneAuthCredential as K, inMemoryPersistence as L, EmailAuthProvider as M, FacebookAuthProvider as N, OperationType as O, PhoneAuthProvider as P, GoogleAuthProvider as Q, RecaptchaVerifier as R, SignInMethod as S, GithubAuthProvider as T, OAuthProvider as U, SAMLAuthProvider as V, TwitterAuthProvider as W, signInAnonymously as X, signInWithCredential as Y, linkWithCredential as Z, reauthenticateWithCredential as _, browserSessionPersistence as a, sendPasswordResetEmail as a0, confirmPasswordReset as a1, applyActionCode as a2, checkActionCode as a3, verifyPasswordResetCode as a4, createUserWithEmailAndPassword as a5, signInWithEmailAndPassword as a6, sendSignInLinkToEmail as a7, isSignInWithEmailLink as a8, signInWithEmailLink as a9, AuthEventManager as aA, _getRedirectResult as aB, _overrideRedirectResult as aC, _clearRedirectOutcomes as aD, _castAuth as aE, UserImpl as aF, AuthImpl as aG, _getClientVersion as aH, _generateEventId as aI, AuthPopup as aJ, FetchProvider as aK, SAMLAuthCredential as aL, fetchSignInMethodsForEmail as aa, sendEmailVerification as ab, verifyBeforeUpdateEmail as ac, ActionCodeURL as ad, parseActionCodeURL as ae, updateProfile as af, updateEmail as ag, updatePassword as ah, getIdToken as ai, getIdTokenResult as aj, unlink as ak, getAdditionalUserInfo as al, reload as am, getMultiFactorResolver as an, multiFactor as ao, _isIOS7Or8 as ap, debugAssert as aq, _isIOS as ar, _isAndroid as as, _fail as at, _getRedirectUrl as au, _getProjectConfig as av, _createError as aw, _assert as ax, _getInstance as ay, _persistenceKeyName as az, browserLocalPersistence as b, signInWithPopup as c, linkWithPopup as d, reauthenticateWithPopup as e, signInWithRedirect as f, linkWithRedirect as g, reauthenticateWithRedirect as h, indexedDBLocalPersistence as i, getRedirectResult as j, browserPopupRedirectResolver as k, linkWithPhoneNumber as l, PhoneMultiFactorGenerator as m, getAuth as n, ProviderId as o, setPersistence as p, onIdTokenChanged as q, reauthenticateWithPhoneNumber as r, signInWithPhoneNumber as s, beforeAuthStateChanged as t, updatePhoneNumber as u, onAuthStateChanged as v, useDeviceLanguage as w, updateCurrentUser as x, signOut as y, deleteUser as z };
9461
+ //# sourceMappingURL=index-815f1b87.js.map