UNPKG

59.8 kBJavaScriptView Raw
1import { ap as _getInstance, aq as _assert, ar as _signInWithCredential, as as _reauthenticate, at as _link$1, H as AuthCredential, au as signInWithIdp, av as _fail, aw as debugAssert, ax as _persistenceKeyName, ay as _castAuth, az as FederatedAuthProvider, aA as BaseOAuthProvider, aB as _emulatorUrl, aC as _performApiRequest, aD as _isIOS7Or8, aE as _isIOS, aF as _isAndroid, aG as _createError, aH as _isSafari, aI as _isIframe, aJ as _isMobileBrowser, aK as _isIE10 } from './index-f3c5e390.js';
2export { A as ActionCodeOperation, ad as ActionCodeURL, H as AuthCredential, D as AuthErrorCodes, aM as AuthImpl, I as EmailAuthCredential, M as EmailAuthProvider, N as FacebookAuthProvider, F as FactorId, aO as FetchProvider, T as GithubAuthProvider, Q as GoogleAuthProvider, J as OAuthCredential, U as OAuthProvider, O as OperationType, K as PhoneAuthCredential, P as PhoneAuthProvider, m as PhoneMultiFactorGenerator, o as ProviderId, R as RecaptchaVerifier, aP as SAMLAuthCredential, V as SAMLAuthProvider, S as SignInMethod, W as TwitterAuthProvider, aL as UserImpl, aq as _assert, ay as _castAuth, av as _fail, aN as _getClientVersion, ap as _getInstance, ax as _persistenceKeyName, a2 as applyActionCode, t as beforeAuthStateChanged, b as browserLocalPersistence, k as browserPopupRedirectResolver, a as browserSessionPersistence, a3 as checkActionCode, a1 as confirmPasswordReset, G as connectAuthEmulator, a5 as createUserWithEmailAndPassword, B as debugErrorMap, z as deleteUser, aa as fetchSignInMethodsForEmail, al as getAdditionalUserInfo, n as getAuth, ai as getIdToken, aj as getIdTokenResult, an as getMultiFactorResolver, j as getRedirectResult, L as inMemoryPersistence, i as indexedDBLocalPersistence, E as initializeAuth, a8 as isSignInWithEmailLink, Z as linkWithCredential, l as linkWithPhoneNumber, d as linkWithPopup, g as linkWithRedirect, ao as multiFactor, v as onAuthStateChanged, q as onIdTokenChanged, ae as parseActionCodeURL, C as prodErrorMap, _ as reauthenticateWithCredential, r as reauthenticateWithPhoneNumber, e as reauthenticateWithPopup, h as reauthenticateWithRedirect, am as reload, ab as sendEmailVerification, a0 as sendPasswordResetEmail, a7 as sendSignInLinkToEmail, p as setPersistence, X as signInAnonymously, Y as signInWithCredential, $ as signInWithCustomToken, a6 as signInWithEmailAndPassword, a9 as signInWithEmailLink, s as signInWithPhoneNumber, c as signInWithPopup, f as signInWithRedirect, y as signOut, ak as unlink, x as updateCurrentUser, ag as updateEmail, ah as updatePassword, u as updatePhoneNumber, af as updateProfile, w as useDeviceLanguage, ac as verifyBeforeUpdateEmail, a4 as verifyPasswordResetCode } from './index-f3c5e390.js';
3import { querystring, isEmpty, getUA, querystringDecode } from '@firebase/util';
4import 'tslib';
5import { SDK_VERSION } from '@firebase/app';
6import '@firebase/logger';
7import '@firebase/component';
8import 'node-fetch';
9
10/**
11 * @license
12 * Copyright 2020 Google LLC
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 * http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 */
26function _generateEventId(prefix = '', digits = 10) {
27 let random = '';
28 for (let i = 0; i < digits; i++) {
29 random += Math.floor(Math.random() * 10);
30 }
31 return prefix + random;
32}
33
34/**
35 * @license
36 * Copyright 2020 Google LLC.
37 *
38 * Licensed under the Apache License, Version 2.0 (the "License");
39 * you may not use this file except in compliance with the License.
40 * You may obtain a copy of the License at
41 *
42 * http://www.apache.org/licenses/LICENSE-2.0
43 *
44 * Unless required by applicable law or agreed to in writing, software
45 * distributed under the License is distributed on an "AS IS" BASIS,
46 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
47 * See the License for the specific language governing permissions and
48 * limitations under the License.
49 */
50class AuthPopup {
51 constructor(window) {
52 this.window = window;
53 this.associatedEvent = null;
54 }
55 close() {
56 if (this.window) {
57 try {
58 this.window.close();
59 }
60 catch (e) { }
61 }
62 }
63}
64
65/**
66 * @license
67 * Copyright 2021 Google LLC
68 *
69 * Licensed under the Apache License, Version 2.0 (the "License");
70 * you may not use this file except in compliance with the License.
71 * You may obtain a copy of the License at
72 *
73 * http://www.apache.org/licenses/LICENSE-2.0
74 *
75 * Unless required by applicable law or agreed to in writing, software
76 * distributed under the License is distributed on an "AS IS" BASIS,
77 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78 * See the License for the specific language governing permissions and
79 * limitations under the License.
80 */
81/**
82 * Chooses a popup/redirect resolver to use. This prefers the override (which
83 * is directly passed in), and falls back to the property set on the auth
84 * object. If neither are available, this function errors w/ an argument error.
85 */
86function _withDefaultResolver(auth, resolverOverride) {
87 if (resolverOverride) {
88 return _getInstance(resolverOverride);
89 }
90 _assert(auth._popupRedirectResolver, auth, "argument-error" /* ARGUMENT_ERROR */);
91 return auth._popupRedirectResolver;
92}
93
94/**
95 * @license
96 * Copyright 2019 Google LLC
97 *
98 * Licensed under the Apache License, Version 2.0 (the "License");
99 * you may not use this file except in compliance with the License.
100 * You may obtain a copy of the License at
101 *
102 * http://www.apache.org/licenses/LICENSE-2.0
103 *
104 * Unless required by applicable law or agreed to in writing, software
105 * distributed under the License is distributed on an "AS IS" BASIS,
106 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107 * See the License for the specific language governing permissions and
108 * limitations under the License.
109 */
110class IdpCredential extends AuthCredential {
111 constructor(params) {
112 super("custom" /* CUSTOM */, "custom" /* CUSTOM */);
113 this.params = params;
114 }
115 _getIdTokenResponse(auth) {
116 return signInWithIdp(auth, this._buildIdpRequest());
117 }
118 _linkToIdToken(auth, idToken) {
119 return signInWithIdp(auth, this._buildIdpRequest(idToken));
120 }
121 _getReauthenticationResolver(auth) {
122 return signInWithIdp(auth, this._buildIdpRequest());
123 }
124 _buildIdpRequest(idToken) {
125 const request = {
126 requestUri: this.params.requestUri,
127 sessionId: this.params.sessionId,
128 postBody: this.params.postBody,
129 tenantId: this.params.tenantId,
130 pendingToken: this.params.pendingToken,
131 returnSecureToken: true,
132 returnIdpCredential: true
133 };
134 if (idToken) {
135 request.idToken = idToken;
136 }
137 return request;
138 }
139}
140function _signIn(params) {
141 return _signInWithCredential(params.auth, new IdpCredential(params), params.bypassAuthState);
142}
143function _reauth(params) {
144 const { auth, user } = params;
145 _assert(user, auth, "internal-error" /* INTERNAL_ERROR */);
146 return _reauthenticate(user, new IdpCredential(params), params.bypassAuthState);
147}
148async function _link(params) {
149 const { auth, user } = params;
150 _assert(user, auth, "internal-error" /* INTERNAL_ERROR */);
151 return _link$1(user, new IdpCredential(params), params.bypassAuthState);
152}
153
154/**
155 * @license
156 * Copyright 2020 Google LLC
157 *
158 * Licensed under the Apache License, Version 2.0 (the "License");
159 * you may not use this file except in compliance with the License.
160 * You may obtain a copy of the License at
161 *
162 * http://www.apache.org/licenses/LICENSE-2.0
163 *
164 * Unless required by applicable law or agreed to in writing, software
165 * distributed under the License is distributed on an "AS IS" BASIS,
166 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
167 * See the License for the specific language governing permissions and
168 * limitations under the License.
169 */
170/**
171 * Popup event manager. Handles the popup's entire lifecycle; listens to auth
172 * events
173 */
174class AbstractPopupRedirectOperation {
175 constructor(auth, filter, resolver, user, bypassAuthState = false) {
176 this.auth = auth;
177 this.resolver = resolver;
178 this.user = user;
179 this.bypassAuthState = bypassAuthState;
180 this.pendingPromise = null;
181 this.eventManager = null;
182 this.filter = Array.isArray(filter) ? filter : [filter];
183 }
184 execute() {
185 return new Promise(async (resolve, reject) => {
186 this.pendingPromise = { resolve, reject };
187 try {
188 this.eventManager = await this.resolver._initialize(this.auth);
189 await this.onExecution();
190 this.eventManager.registerConsumer(this);
191 }
192 catch (e) {
193 this.reject(e);
194 }
195 });
196 }
197 async onAuthEvent(event) {
198 const { urlResponse, sessionId, postBody, tenantId, error, type } = event;
199 if (error) {
200 this.reject(error);
201 return;
202 }
203 const params = {
204 auth: this.auth,
205 requestUri: urlResponse,
206 sessionId: sessionId,
207 tenantId: tenantId || undefined,
208 postBody: postBody || undefined,
209 user: this.user,
210 bypassAuthState: this.bypassAuthState
211 };
212 try {
213 this.resolve(await this.getIdpTask(type)(params));
214 }
215 catch (e) {
216 this.reject(e);
217 }
218 }
219 onError(error) {
220 this.reject(error);
221 }
222 getIdpTask(type) {
223 switch (type) {
224 case "signInViaPopup" /* SIGN_IN_VIA_POPUP */:
225 case "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */:
226 return _signIn;
227 case "linkViaPopup" /* LINK_VIA_POPUP */:
228 case "linkViaRedirect" /* LINK_VIA_REDIRECT */:
229 return _link;
230 case "reauthViaPopup" /* REAUTH_VIA_POPUP */:
231 case "reauthViaRedirect" /* REAUTH_VIA_REDIRECT */:
232 return _reauth;
233 default:
234 _fail(this.auth, "internal-error" /* INTERNAL_ERROR */);
235 }
236 }
237 resolve(cred) {
238 debugAssert(this.pendingPromise, 'Pending promise was never set');
239 this.pendingPromise.resolve(cred);
240 this.unregisterAndCleanUp();
241 }
242 reject(error) {
243 debugAssert(this.pendingPromise, 'Pending promise was never set');
244 this.pendingPromise.reject(error);
245 this.unregisterAndCleanUp();
246 }
247 unregisterAndCleanUp() {
248 if (this.eventManager) {
249 this.eventManager.unregisterConsumer(this);
250 }
251 this.pendingPromise = null;
252 this.cleanUp();
253 }
254}
255
256/**
257 * @license
258 * Copyright 2020 Google LLC
259 *
260 * Licensed under the Apache License, Version 2.0 (the "License");
261 * you may not use this file except in compliance with the License.
262 * You may obtain a copy of the License at
263 *
264 * http://www.apache.org/licenses/LICENSE-2.0
265 *
266 * Unless required by applicable law or agreed to in writing, software
267 * distributed under the License is distributed on an "AS IS" BASIS,
268 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
269 * See the License for the specific language governing permissions and
270 * limitations under the License.
271 */
272const PENDING_REDIRECT_KEY = 'pendingRedirect';
273// We only get one redirect outcome for any one auth, so just store it
274// in here.
275const redirectOutcomeMap = new Map();
276class RedirectAction extends AbstractPopupRedirectOperation {
277 constructor(auth, resolver, bypassAuthState = false) {
278 super(auth, [
279 "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */,
280 "linkViaRedirect" /* LINK_VIA_REDIRECT */,
281 "reauthViaRedirect" /* REAUTH_VIA_REDIRECT */,
282 "unknown" /* UNKNOWN */
283 ], resolver, undefined, bypassAuthState);
284 this.eventId = null;
285 }
286 /**
287 * Override the execute function; if we already have a redirect result, then
288 * just return it.
289 */
290 async execute() {
291 let readyOutcome = redirectOutcomeMap.get(this.auth._key());
292 if (!readyOutcome) {
293 try {
294 const hasPendingRedirect = await _getAndClearPendingRedirectStatus(this.resolver, this.auth);
295 const result = hasPendingRedirect ? await super.execute() : null;
296 readyOutcome = () => Promise.resolve(result);
297 }
298 catch (e) {
299 readyOutcome = () => Promise.reject(e);
300 }
301 redirectOutcomeMap.set(this.auth._key(), readyOutcome);
302 }
303 // If we're not bypassing auth state, the ready outcome should be set to
304 // null.
305 if (!this.bypassAuthState) {
306 redirectOutcomeMap.set(this.auth._key(), () => Promise.resolve(null));
307 }
308 return readyOutcome();
309 }
310 async onAuthEvent(event) {
311 if (event.type === "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */) {
312 return super.onAuthEvent(event);
313 }
314 else if (event.type === "unknown" /* UNKNOWN */) {
315 // This is a sentinel value indicating there's no pending redirect
316 this.resolve(null);
317 return;
318 }
319 if (event.eventId) {
320 const user = await this.auth._redirectUserForId(event.eventId);
321 if (user) {
322 this.user = user;
323 return super.onAuthEvent(event);
324 }
325 else {
326 this.resolve(null);
327 }
328 }
329 }
330 async onExecution() { }
331 cleanUp() { }
332}
333async function _getAndClearPendingRedirectStatus(resolver, auth) {
334 const key = pendingRedirectKey(auth);
335 const persistence = resolverPersistence(resolver);
336 if (!(await persistence._isAvailable())) {
337 return false;
338 }
339 const hasPendingRedirect = (await persistence._get(key)) === 'true';
340 await persistence._remove(key);
341 return hasPendingRedirect;
342}
343function _clearRedirectOutcomes() {
344 redirectOutcomeMap.clear();
345}
346function _overrideRedirectResult(auth, result) {
347 redirectOutcomeMap.set(auth._key(), result);
348}
349function resolverPersistence(resolver) {
350 return _getInstance(resolver._redirectPersistence);
351}
352function pendingRedirectKey(auth) {
353 return _persistenceKeyName(PENDING_REDIRECT_KEY, auth.config.apiKey, auth.name);
354}
355
356/**
357 * @license
358 * Copyright 2020 Google LLC
359 *
360 * Licensed under the Apache License, Version 2.0 (the "License");
361 * you may not use this file except in compliance with the License.
362 * You may obtain a copy of the License at
363 *
364 * http://www.apache.org/licenses/LICENSE-2.0
365 *
366 * Unless required by applicable law or agreed to in writing, software
367 * distributed under the License is distributed on an "AS IS" BASIS,
368 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
369 * See the License for the specific language governing permissions and
370 * limitations under the License.
371 */
372async function _getRedirectResult(auth, resolverExtern, bypassAuthState = false) {
373 const authInternal = _castAuth(auth);
374 const resolver = _withDefaultResolver(authInternal, resolverExtern);
375 const action = new RedirectAction(authInternal, resolver, bypassAuthState);
376 const result = await action.execute();
377 if (result && !bypassAuthState) {
378 delete result.user._redirectEventId;
379 await authInternal._persistUserIfCurrent(result.user);
380 await authInternal._setRedirectUser(null, resolverExtern);
381 }
382 return result;
383}
384
385const STORAGE_AVAILABLE_KEY = '__sak';
386
387/**
388 * @license
389 * Copyright 2019 Google LLC
390 *
391 * Licensed under the Apache License, Version 2.0 (the "License");
392 * you may not use this file except in compliance with the License.
393 * You may obtain a copy of the License at
394 *
395 * http://www.apache.org/licenses/LICENSE-2.0
396 *
397 * Unless required by applicable law or agreed to in writing, software
398 * distributed under the License is distributed on an "AS IS" BASIS,
399 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
400 * See the License for the specific language governing permissions and
401 * limitations under the License.
402 */
403// There are two different browser persistence types: local and session.
404// Both have the same implementation but use a different underlying storage
405// object.
406class BrowserPersistenceClass {
407 constructor(storageRetriever, type) {
408 this.storageRetriever = storageRetriever;
409 this.type = type;
410 }
411 _isAvailable() {
412 try {
413 if (!this.storage) {
414 return Promise.resolve(false);
415 }
416 this.storage.setItem(STORAGE_AVAILABLE_KEY, '1');
417 this.storage.removeItem(STORAGE_AVAILABLE_KEY);
418 return Promise.resolve(true);
419 }
420 catch (_a) {
421 return Promise.resolve(false);
422 }
423 }
424 _set(key, value) {
425 this.storage.setItem(key, JSON.stringify(value));
426 return Promise.resolve();
427 }
428 _get(key) {
429 const json = this.storage.getItem(key);
430 return Promise.resolve(json ? JSON.parse(json) : null);
431 }
432 _remove(key) {
433 this.storage.removeItem(key);
434 return Promise.resolve();
435 }
436 get storage() {
437 return this.storageRetriever();
438 }
439}
440
441/**
442 * @license
443 * Copyright 2020 Google LLC
444 *
445 * Licensed under the Apache License, Version 2.0 (the "License");
446 * you may not use this file except in compliance with the License.
447 * You may obtain a copy of the License at
448 *
449 * http://www.apache.org/licenses/LICENSE-2.0
450 *
451 * Unless required by applicable law or agreed to in writing, software
452 * distributed under the License is distributed on an "AS IS" BASIS,
453 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
454 * See the License for the specific language governing permissions and
455 * limitations under the License.
456 */
457class BrowserSessionPersistence extends BrowserPersistenceClass {
458 constructor() {
459 super(() => window.sessionStorage, "SESSION" /* SESSION */);
460 }
461 _addListener(_key, _listener) {
462 // Listeners are not supported for session storage since it cannot be shared across windows
463 return;
464 }
465 _removeListener(_key, _listener) {
466 // Listeners are not supported for session storage since it cannot be shared across windows
467 return;
468 }
469}
470BrowserSessionPersistence.type = 'SESSION';
471/**
472 * An implementation of {@link Persistence} of `SESSION` using `sessionStorage`
473 * for the underlying storage.
474 *
475 * @public
476 */
477const browserSessionPersistence = BrowserSessionPersistence;
478
479/**
480 * @license
481 * Copyright 2021 Google LLC
482 *
483 * Licensed under the Apache License, Version 2.0 (the "License");
484 * you may not use this file except in compliance with the License.
485 * You may obtain a copy of the License at
486 *
487 * http://www.apache.org/licenses/LICENSE-2.0
488 *
489 * Unless required by applicable law or agreed to in writing, software
490 * distributed under the License is distributed on an "AS IS" BASIS,
491 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
492 * See the License for the specific language governing permissions and
493 * limitations under the License.
494 */
495/**
496 * URL for Authentication widget which will initiate the OAuth handshake
497 *
498 * @internal
499 */
500const WIDGET_PATH = '__/auth/handler';
501/**
502 * URL for emulated environment
503 *
504 * @internal
505 */
506const EMULATOR_WIDGET_PATH = 'emulator/auth/handler';
507function _getRedirectUrl(auth, provider, authType, redirectUrl, eventId, additionalParams) {
508 _assert(auth.config.authDomain, auth, "auth-domain-config-required" /* MISSING_AUTH_DOMAIN */);
509 _assert(auth.config.apiKey, auth, "invalid-api-key" /* INVALID_API_KEY */);
510 const params = {
511 apiKey: auth.config.apiKey,
512 appName: auth.name,
513 authType,
514 redirectUrl,
515 v: SDK_VERSION,
516 eventId
517 };
518 if (provider instanceof FederatedAuthProvider) {
519 provider.setDefaultLanguage(auth.languageCode);
520 params.providerId = provider.providerId || '';
521 if (!isEmpty(provider.getCustomParameters())) {
522 params.customParameters = JSON.stringify(provider.getCustomParameters());
523 }
524 // TODO set additionalParams from the provider as well?
525 for (const [key, value] of Object.entries(additionalParams || {})) {
526 params[key] = value;
527 }
528 }
529 if (provider instanceof BaseOAuthProvider) {
530 const scopes = provider.getScopes().filter(scope => scope !== '');
531 if (scopes.length > 0) {
532 params.scopes = scopes.join(',');
533 }
534 }
535 if (auth.tenantId) {
536 params.tid = auth.tenantId;
537 }
538 // TODO: maybe set eid as endipointId
539 // TODO: maybe set fw as Frameworks.join(",")
540 const paramsDict = params;
541 for (const key of Object.keys(paramsDict)) {
542 if (paramsDict[key] === undefined) {
543 delete paramsDict[key];
544 }
545 }
546 return `${getHandlerBase(auth)}?${querystring(paramsDict).slice(1)}`;
547}
548function getHandlerBase({ config }) {
549 if (!config.emulator) {
550 return `https://${config.authDomain}/${WIDGET_PATH}`;
551 }
552 return _emulatorUrl(config, EMULATOR_WIDGET_PATH);
553}
554
555/**
556 * @license
557 * Copyright 2021 Google LLC
558 *
559 * Licensed under the Apache License, Version 2.0 (the "License");
560 * you may not use this file except in compliance with the License.
561 * You may obtain a copy of the License at
562 *
563 * http://www.apache.org/licenses/LICENSE-2.0
564 *
565 * Unless required by applicable law or agreed to in writing, software
566 * distributed under the License is distributed on an "AS IS" BASIS,
567 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
568 * See the License for the specific language governing permissions and
569 * limitations under the License.
570 */
571function _cordovaWindow() {
572 return window;
573}
574
575/**
576 * @license
577 * Copyright 2020 Google LLC
578 *
579 * Licensed under the Apache License, Version 2.0 (the "License");
580 * you may not use this file except in compliance with the License.
581 * You may obtain a copy of the License at
582 *
583 * http://www.apache.org/licenses/LICENSE-2.0
584 *
585 * Unless required by applicable law or agreed to in writing, software
586 * distributed under the License is distributed on an "AS IS" BASIS,
587 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
588 * See the License for the specific language governing permissions and
589 * limitations under the License.
590 */
591async function _getProjectConfig(auth, request = {}) {
592 return _performApiRequest(auth, "GET" /* GET */, "/v1/projects" /* GET_PROJECT_CONFIG */, request);
593}
594
595/**
596 * @license
597 * Copyright 2020 Google LLC
598 *
599 * Licensed under the Apache License, Version 2.0 (the "License");
600 * you may not use this file except in compliance with the License.
601 * You may obtain a copy of the License at
602 *
603 * http://www.apache.org/licenses/LICENSE-2.0
604 *
605 * Unless required by applicable law or agreed to in writing, software
606 * distributed under the License is distributed on an "AS IS" BASIS,
607 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
608 * See the License for the specific language governing permissions and
609 * limitations under the License.
610 */
611/**
612 * How long to wait after the app comes back into focus before concluding that
613 * the user closed the sign in tab.
614 */
615const REDIRECT_TIMEOUT_MS = 2000;
616/**
617 * Generates the URL for the OAuth handler.
618 */
619async function _generateHandlerUrl(auth, event, provider) {
620 var _a;
621 // Get the cordova plugins
622 const { BuildInfo } = _cordovaWindow();
623 debugAssert(event.sessionId, 'AuthEvent did not contain a session ID');
624 const sessionDigest = await computeSha256(event.sessionId);
625 const additionalParams = {};
626 if (_isIOS()) {
627 // iOS app identifier
628 additionalParams['ibi'] = BuildInfo.packageName;
629 }
630 else if (_isAndroid()) {
631 // Android app identifier
632 additionalParams['apn'] = BuildInfo.packageName;
633 }
634 else {
635 _fail(auth, "operation-not-supported-in-this-environment" /* OPERATION_NOT_SUPPORTED */);
636 }
637 // Add the display name if available
638 if (BuildInfo.displayName) {
639 additionalParams['appDisplayName'] = BuildInfo.displayName;
640 }
641 // Attached the hashed session ID
642 additionalParams['sessionId'] = sessionDigest;
643 return _getRedirectUrl(auth, provider, event.type, undefined, (_a = event.eventId) !== null && _a !== void 0 ? _a : undefined, additionalParams);
644}
645/**
646 * Validates that this app is valid for this project configuration
647 */
648async function _validateOrigin(auth) {
649 const { BuildInfo } = _cordovaWindow();
650 const request = {};
651 if (_isIOS()) {
652 request.iosBundleId = BuildInfo.packageName;
653 }
654 else if (_isAndroid()) {
655 request.androidPackageName = BuildInfo.packageName;
656 }
657 else {
658 _fail(auth, "operation-not-supported-in-this-environment" /* OPERATION_NOT_SUPPORTED */);
659 }
660 // Will fail automatically if package name is not authorized
661 await _getProjectConfig(auth, request);
662}
663function _performRedirect(handlerUrl) {
664 // Get the cordova plugins
665 const { cordova } = _cordovaWindow();
666 return new Promise(resolve => {
667 cordova.plugins.browsertab.isAvailable(browserTabIsAvailable => {
668 let iabRef = null;
669 if (browserTabIsAvailable) {
670 cordova.plugins.browsertab.openUrl(handlerUrl);
671 }
672 else {
673 // TODO: Return the inappbrowser ref that's returned from the open call
674 iabRef = cordova.InAppBrowser.open(handlerUrl, _isIOS7Or8() ? '_blank' : '_system', 'location=yes');
675 }
676 resolve(iabRef);
677 });
678 });
679}
680/**
681 * This function waits for app activity to be seen before resolving. It does
682 * this by attaching listeners to various dom events. Once the app is determined
683 * to be visible, this promise resolves. AFTER that resolution, the listeners
684 * are detached and any browser tabs left open will be closed.
685 */
686async function _waitForAppResume(auth, eventListener, iabRef) {
687 // Get the cordova plugins
688 const { cordova } = _cordovaWindow();
689 let cleanup = () => { };
690 try {
691 await new Promise((resolve, reject) => {
692 let onCloseTimer = null;
693 // DEFINE ALL THE CALLBACKS =====
694 function authEventSeen() {
695 var _a;
696 // Auth event was detected. Resolve this promise and close the extra
697 // window if it's still open.
698 resolve();
699 const closeBrowserTab = (_a = cordova.plugins.browsertab) === null || _a === void 0 ? void 0 : _a.close;
700 if (typeof closeBrowserTab === 'function') {
701 closeBrowserTab();
702 }
703 // Close inappbrowser emebedded webview in iOS7 and 8 case if still
704 // open.
705 if (typeof (iabRef === null || iabRef === void 0 ? void 0 : iabRef.close) === 'function') {
706 iabRef.close();
707 }
708 }
709 function resumed() {
710 if (onCloseTimer) {
711 // This code already ran; do not rerun.
712 return;
713 }
714 onCloseTimer = window.setTimeout(() => {
715 // Wait two seeconds after resume then reject.
716 reject(_createError(auth, "redirect-cancelled-by-user" /* REDIRECT_CANCELLED_BY_USER */));
717 }, REDIRECT_TIMEOUT_MS);
718 }
719 function visibilityChanged() {
720 if ((document === null || document === void 0 ? void 0 : document.visibilityState) === 'visible') {
721 resumed();
722 }
723 }
724 // ATTACH ALL THE LISTENERS =====
725 // Listen for the auth event
726 eventListener.addPassiveListener(authEventSeen);
727 // Listen for resume and visibility events
728 document.addEventListener('resume', resumed, false);
729 if (_isAndroid()) {
730 document.addEventListener('visibilitychange', visibilityChanged, false);
731 }
732 // SETUP THE CLEANUP FUNCTION =====
733 cleanup = () => {
734 eventListener.removePassiveListener(authEventSeen);
735 document.removeEventListener('resume', resumed, false);
736 document.removeEventListener('visibilitychange', visibilityChanged, false);
737 if (onCloseTimer) {
738 window.clearTimeout(onCloseTimer);
739 }
740 };
741 });
742 }
743 finally {
744 cleanup();
745 }
746}
747/**
748 * Checks the configuration of the Cordova environment. This has no side effect
749 * if the configuration is correct; otherwise it throws an error with the
750 * missing plugin.
751 */
752function _checkCordovaConfiguration(auth) {
753 var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
754 const win = _cordovaWindow();
755 // Check all dependencies installed.
756 // https://github.com/nordnet/cordova-universal-links-plugin
757 // Note that cordova-universal-links-plugin has been abandoned.
758 // A fork with latest fixes is available at:
759 // https://www.npmjs.com/package/cordova-universal-links-plugin-fix
760 _assert(typeof ((_a = win === null || win === void 0 ? void 0 : win.universalLinks) === null || _a === void 0 ? void 0 : _a.subscribe) === 'function', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
761 missingPlugin: 'cordova-universal-links-plugin-fix'
762 });
763 // https://www.npmjs.com/package/cordova-plugin-buildinfo
764 _assert(typeof ((_b = win === null || win === void 0 ? void 0 : win.BuildInfo) === null || _b === void 0 ? void 0 : _b.packageName) !== 'undefined', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
765 missingPlugin: 'cordova-plugin-buildInfo'
766 });
767 // https://github.com/google/cordova-plugin-browsertab
768 _assert(typeof ((_e = (_d = (_c = win === null || win === void 0 ? void 0 : win.cordova) === null || _c === void 0 ? void 0 : _c.plugins) === null || _d === void 0 ? void 0 : _d.browsertab) === null || _e === void 0 ? void 0 : _e.openUrl) === 'function', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
769 missingPlugin: 'cordova-plugin-browsertab'
770 });
771 _assert(typeof ((_h = (_g = (_f = win === null || win === void 0 ? void 0 : win.cordova) === null || _f === void 0 ? void 0 : _f.plugins) === null || _g === void 0 ? void 0 : _g.browsertab) === null || _h === void 0 ? void 0 : _h.isAvailable) === 'function', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
772 missingPlugin: 'cordova-plugin-browsertab'
773 });
774 // https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/
775 _assert(typeof ((_k = (_j = win === null || win === void 0 ? void 0 : win.cordova) === null || _j === void 0 ? void 0 : _j.InAppBrowser) === null || _k === void 0 ? void 0 : _k.open) === 'function', auth, "invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */, {
776 missingPlugin: 'cordova-plugin-inappbrowser'
777 });
778}
779/**
780 * Computes the SHA-256 of a session ID. The SubtleCrypto interface is only
781 * available in "secure" contexts, which covers Cordova (which is served on a file
782 * protocol).
783 */
784async function computeSha256(sessionId) {
785 const bytes = stringToArrayBuffer(sessionId);
786 // TODO: For IE11 crypto has a different name and this operation comes back
787 // as an object, not a promise. This is the old proposed standard that
788 // is used by IE11:
789 // https://www.w3.org/TR/2013/WD-WebCryptoAPI-20130108/#cryptooperation-interface
790 const buf = await crypto.subtle.digest('SHA-256', bytes);
791 const arr = Array.from(new Uint8Array(buf));
792 return arr.map(num => num.toString(16).padStart(2, '0')).join('');
793}
794function stringToArrayBuffer(str) {
795 // This function is only meant to deal with an ASCII charset and makes
796 // certain simplifying assumptions.
797 debugAssert(/[0-9a-zA-Z]+/.test(str), 'Can only convert alpha-numeric strings');
798 if (typeof TextEncoder !== 'undefined') {
799 return new TextEncoder().encode(str);
800 }
801 const buff = new ArrayBuffer(str.length);
802 const view = new Uint8Array(buff);
803 for (let i = 0; i < str.length; i++) {
804 view[i] = str.charCodeAt(i);
805 }
806 return view;
807}
808
809/**
810 * @license
811 * Copyright 2020 Google LLC
812 *
813 * Licensed under the Apache License, Version 2.0 (the "License");
814 * you may not use this file except in compliance with the License.
815 * You may obtain a copy of the License at
816 *
817 * http://www.apache.org/licenses/LICENSE-2.0
818 *
819 * Unless required by applicable law or agreed to in writing, software
820 * distributed under the License is distributed on an "AS IS" BASIS,
821 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
822 * See the License for the specific language governing permissions and
823 * limitations under the License.
824 */
825// The amount of time to store the UIDs of seen events; this is
826// set to 10 min by default
827const EVENT_DUPLICATION_CACHE_DURATION_MS = 10 * 60 * 1000;
828class AuthEventManager {
829 constructor(auth) {
830 this.auth = auth;
831 this.cachedEventUids = new Set();
832 this.consumers = new Set();
833 this.queuedRedirectEvent = null;
834 this.hasHandledPotentialRedirect = false;
835 this.lastProcessedEventTime = Date.now();
836 }
837 registerConsumer(authEventConsumer) {
838 this.consumers.add(authEventConsumer);
839 if (this.queuedRedirectEvent &&
840 this.isEventForConsumer(this.queuedRedirectEvent, authEventConsumer)) {
841 this.sendToConsumer(this.queuedRedirectEvent, authEventConsumer);
842 this.saveEventToCache(this.queuedRedirectEvent);
843 this.queuedRedirectEvent = null;
844 }
845 }
846 unregisterConsumer(authEventConsumer) {
847 this.consumers.delete(authEventConsumer);
848 }
849 onEvent(event) {
850 // Check if the event has already been handled
851 if (this.hasEventBeenHandled(event)) {
852 return false;
853 }
854 let handled = false;
855 this.consumers.forEach(consumer => {
856 if (this.isEventForConsumer(event, consumer)) {
857 handled = true;
858 this.sendToConsumer(event, consumer);
859 this.saveEventToCache(event);
860 }
861 });
862 if (this.hasHandledPotentialRedirect || !isRedirectEvent(event)) {
863 // If we've already seen a redirect before, or this is a popup event,
864 // bail now
865 return handled;
866 }
867 this.hasHandledPotentialRedirect = true;
868 // If the redirect wasn't handled, hang on to it
869 if (!handled) {
870 this.queuedRedirectEvent = event;
871 handled = true;
872 }
873 return handled;
874 }
875 sendToConsumer(event, consumer) {
876 var _a;
877 if (event.error && !isNullRedirectEvent(event)) {
878 const code = ((_a = event.error.code) === null || _a === void 0 ? void 0 : _a.split('auth/')[1]) ||
879 "internal-error" /* INTERNAL_ERROR */;
880 consumer.onError(_createError(this.auth, code));
881 }
882 else {
883 consumer.onAuthEvent(event);
884 }
885 }
886 isEventForConsumer(event, consumer) {
887 const eventIdMatches = consumer.eventId === null ||
888 (!!event.eventId && event.eventId === consumer.eventId);
889 return consumer.filter.includes(event.type) && eventIdMatches;
890 }
891 hasEventBeenHandled(event) {
892 if (Date.now() - this.lastProcessedEventTime >=
893 EVENT_DUPLICATION_CACHE_DURATION_MS) {
894 this.cachedEventUids.clear();
895 }
896 return this.cachedEventUids.has(eventUid(event));
897 }
898 saveEventToCache(event) {
899 this.cachedEventUids.add(eventUid(event));
900 this.lastProcessedEventTime = Date.now();
901 }
902}
903function eventUid(e) {
904 return [e.type, e.eventId, e.sessionId, e.tenantId].filter(v => v).join('-');
905}
906function isNullRedirectEvent({ type, error }) {
907 return (type === "unknown" /* UNKNOWN */ &&
908 (error === null || error === void 0 ? void 0 : error.code) === `auth/${"no-auth-event" /* NO_AUTH_EVENT */}`);
909}
910function isRedirectEvent(event) {
911 switch (event.type) {
912 case "signInViaRedirect" /* SIGN_IN_VIA_REDIRECT */:
913 case "linkViaRedirect" /* LINK_VIA_REDIRECT */:
914 case "reauthViaRedirect" /* REAUTH_VIA_REDIRECT */:
915 return true;
916 case "unknown" /* UNKNOWN */:
917 return isNullRedirectEvent(event);
918 default:
919 return false;
920 }
921}
922
923/**
924 * @license
925 * Copyright 2020 Google LLC
926 *
927 * Licensed under the Apache License, Version 2.0 (the "License");
928 * you may not use this file except in compliance with the License.
929 * You may obtain a copy of the License at
930 *
931 * http://www.apache.org/licenses/LICENSE-2.0
932 *
933 * Unless required by applicable law or agreed to in writing, software
934 * distributed under the License is distributed on an "AS IS" BASIS,
935 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
936 * See the License for the specific language governing permissions and
937 * limitations under the License.
938 */
939function _iframeCannotSyncWebStorage() {
940 const ua = getUA();
941 return _isSafari(ua) || _isIOS(ua);
942}
943// The polling period in case events are not supported
944const _POLLING_INTERVAL_MS = 1000;
945// The IE 10 localStorage cross tab synchronization delay in milliseconds
946const IE10_LOCAL_STORAGE_SYNC_DELAY = 10;
947class BrowserLocalPersistence extends BrowserPersistenceClass {
948 constructor() {
949 super(() => window.localStorage, "LOCAL" /* LOCAL */);
950 this.boundEventHandler = (event, poll) => this.onStorageEvent(event, poll);
951 this.listeners = {};
952 this.localCache = {};
953 // setTimeout return value is platform specific
954 // eslint-disable-next-line @typescript-eslint/no-explicit-any
955 this.pollTimer = null;
956 // Safari or iOS browser and embedded in an iframe.
957 this.safariLocalStorageNotSynced = _iframeCannotSyncWebStorage() && _isIframe();
958 // Whether to use polling instead of depending on window events
959 this.fallbackToPolling = _isMobileBrowser();
960 this._shouldAllowMigration = true;
961 }
962 forAllChangedKeys(cb) {
963 // Check all keys with listeners on them.
964 for (const key of Object.keys(this.listeners)) {
965 // Get value from localStorage.
966 const newValue = this.storage.getItem(key);
967 const oldValue = this.localCache[key];
968 // If local map value does not match, trigger listener with storage event.
969 // Differentiate this simulated event from the real storage event.
970 if (newValue !== oldValue) {
971 cb(key, oldValue, newValue);
972 }
973 }
974 }
975 onStorageEvent(event, poll = false) {
976 // Key would be null in some situations, like when localStorage is cleared
977 if (!event.key) {
978 this.forAllChangedKeys((key, _oldValue, newValue) => {
979 this.notifyListeners(key, newValue);
980 });
981 return;
982 }
983 const key = event.key;
984 // Check the mechanism how this event was detected.
985 // The first event will dictate the mechanism to be used.
986 if (poll) {
987 // Environment detects storage changes via polling.
988 // Remove storage event listener to prevent possible event duplication.
989 this.detachListener();
990 }
991 else {
992 // Environment detects storage changes via storage event listener.
993 // Remove polling listener to prevent possible event duplication.
994 this.stopPolling();
995 }
996 // Safari embedded iframe. Storage event will trigger with the delta
997 // changes but no changes will be applied to the iframe localStorage.
998 if (this.safariLocalStorageNotSynced) {
999 // Get current iframe page value.
1000 const storedValue = this.storage.getItem(key);
1001 // Value not synchronized, synchronize manually.
1002 if (event.newValue !== storedValue) {
1003 if (event.newValue !== null) {
1004 // Value changed from current value.
1005 this.storage.setItem(key, event.newValue);
1006 }
1007 else {
1008 // Current value deleted.
1009 this.storage.removeItem(key);
1010 }
1011 }
1012 else if (this.localCache[key] === event.newValue && !poll) {
1013 // Already detected and processed, do not trigger listeners again.
1014 return;
1015 }
1016 }
1017 const triggerListeners = () => {
1018 // Keep local map up to date in case storage event is triggered before
1019 // poll.
1020 const storedValue = this.storage.getItem(key);
1021 if (!poll && this.localCache[key] === storedValue) {
1022 // Real storage event which has already been detected, do nothing.
1023 // This seems to trigger in some IE browsers for some reason.
1024 return;
1025 }
1026 this.notifyListeners(key, storedValue);
1027 };
1028 const storedValue = this.storage.getItem(key);
1029 if (_isIE10() &&
1030 storedValue !== event.newValue &&
1031 event.newValue !== event.oldValue) {
1032 // IE 10 has this weird bug where a storage event would trigger with the
1033 // correct key, oldValue and newValue but localStorage.getItem(key) does
1034 // not yield the updated value until a few milliseconds. This ensures
1035 // this recovers from that situation.
1036 setTimeout(triggerListeners, IE10_LOCAL_STORAGE_SYNC_DELAY);
1037 }
1038 else {
1039 triggerListeners();
1040 }
1041 }
1042 notifyListeners(key, value) {
1043 this.localCache[key] = value;
1044 const listeners = this.listeners[key];
1045 if (listeners) {
1046 for (const listener of Array.from(listeners)) {
1047 listener(value ? JSON.parse(value) : value);
1048 }
1049 }
1050 }
1051 startPolling() {
1052 this.stopPolling();
1053 this.pollTimer = setInterval(() => {
1054 this.forAllChangedKeys((key, oldValue, newValue) => {
1055 this.onStorageEvent(new StorageEvent('storage', {
1056 key,
1057 oldValue,
1058 newValue
1059 }),
1060 /* poll */ true);
1061 });
1062 }, _POLLING_INTERVAL_MS);
1063 }
1064 stopPolling() {
1065 if (this.pollTimer) {
1066 clearInterval(this.pollTimer);
1067 this.pollTimer = null;
1068 }
1069 }
1070 attachListener() {
1071 window.addEventListener('storage', this.boundEventHandler);
1072 }
1073 detachListener() {
1074 window.removeEventListener('storage', this.boundEventHandler);
1075 }
1076 _addListener(key, listener) {
1077 if (Object.keys(this.listeners).length === 0) {
1078 // Whether browser can detect storage event when it had already been pushed to the background.
1079 // This may happen in some mobile browsers. A localStorage change in the foreground window
1080 // will not be detected in the background window via the storage event.
1081 // This was detected in iOS 7.x mobile browsers
1082 if (this.fallbackToPolling) {
1083 this.startPolling();
1084 }
1085 else {
1086 this.attachListener();
1087 }
1088 }
1089 if (!this.listeners[key]) {
1090 this.listeners[key] = new Set();
1091 // Populate the cache to avoid spuriously triggering on first poll.
1092 this.localCache[key] = this.storage.getItem(key);
1093 }
1094 this.listeners[key].add(listener);
1095 }
1096 _removeListener(key, listener) {
1097 if (this.listeners[key]) {
1098 this.listeners[key].delete(listener);
1099 if (this.listeners[key].size === 0) {
1100 delete this.listeners[key];
1101 }
1102 }
1103 if (Object.keys(this.listeners).length === 0) {
1104 this.detachListener();
1105 this.stopPolling();
1106 }
1107 }
1108 // Update local cache on base operations:
1109 async _set(key, value) {
1110 await super._set(key, value);
1111 this.localCache[key] = JSON.stringify(value);
1112 }
1113 async _get(key) {
1114 const value = await super._get(key);
1115 this.localCache[key] = JSON.stringify(value);
1116 return value;
1117 }
1118 async _remove(key) {
1119 await super._remove(key);
1120 delete this.localCache[key];
1121 }
1122}
1123BrowserLocalPersistence.type = 'LOCAL';
1124/**
1125 * An implementation of {@link Persistence} of type `LOCAL` using `localStorage`
1126 * for the underlying storage.
1127 *
1128 * @public
1129 */
1130const browserLocalPersistence = BrowserLocalPersistence;
1131
1132/**
1133 * @license
1134 * Copyright 2020 Google LLC
1135 *
1136 * Licensed under the Apache License, Version 2.0 (the "License");
1137 * you may not use this file except in compliance with the License.
1138 * You may obtain a copy of the License at
1139 *
1140 * http://www.apache.org/licenses/LICENSE-2.0
1141 *
1142 * Unless required by applicable law or agreed to in writing, software
1143 * distributed under the License is distributed on an "AS IS" BASIS,
1144 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1145 * See the License for the specific language governing permissions and
1146 * limitations under the License.
1147 */
1148const SESSION_ID_LENGTH = 20;
1149/** Custom AuthEventManager that adds passive listeners to events */
1150class CordovaAuthEventManager extends AuthEventManager {
1151 constructor() {
1152 super(...arguments);
1153 this.passiveListeners = new Set();
1154 this.initPromise = new Promise(resolve => {
1155 this.resolveInialized = resolve;
1156 });
1157 }
1158 addPassiveListener(cb) {
1159 this.passiveListeners.add(cb);
1160 }
1161 removePassiveListener(cb) {
1162 this.passiveListeners.delete(cb);
1163 }
1164 // In a Cordova environment, this manager can live through multiple redirect
1165 // operations
1166 resetRedirect() {
1167 this.queuedRedirectEvent = null;
1168 this.hasHandledPotentialRedirect = false;
1169 }
1170 /** Override the onEvent method */
1171 onEvent(event) {
1172 this.resolveInialized();
1173 this.passiveListeners.forEach(cb => cb(event));
1174 return super.onEvent(event);
1175 }
1176 async initialized() {
1177 await this.initPromise;
1178 }
1179}
1180/**
1181 * Generates a (partial) {@link AuthEvent}.
1182 */
1183function _generateNewEvent(auth, type, eventId = null) {
1184 return {
1185 type,
1186 eventId,
1187 urlResponse: null,
1188 sessionId: generateSessionId(),
1189 postBody: null,
1190 tenantId: auth.tenantId,
1191 error: _createError(auth, "no-auth-event" /* NO_AUTH_EVENT */)
1192 };
1193}
1194function _savePartialEvent(auth, event) {
1195 return storage()._set(persistenceKey(auth), event);
1196}
1197async function _getAndRemoveEvent(auth) {
1198 const event = (await storage()._get(persistenceKey(auth)));
1199 if (event) {
1200 await storage()._remove(persistenceKey(auth));
1201 }
1202 return event;
1203}
1204function _eventFromPartialAndUrl(partialEvent, url) {
1205 var _a, _b;
1206 // Parse the deep link within the dynamic link URL.
1207 const callbackUrl = _getDeepLinkFromCallback(url);
1208 // Confirm it is actually a callback URL.
1209 // Currently the universal link will be of this format:
1210 // https://<AUTH_DOMAIN>/__/auth/callback<OAUTH_RESPONSE>
1211 // This is a fake URL but is not intended to take the user anywhere
1212 // and just redirect to the app.
1213 if (callbackUrl.includes('/__/auth/callback')) {
1214 // Check if there is an error in the URL.
1215 // This mechanism is also used to pass errors back to the app:
1216 // https://<AUTH_DOMAIN>/__/auth/callback?firebaseError=<STRINGIFIED_ERROR>
1217 const params = searchParamsOrEmpty(callbackUrl);
1218 // Get the error object corresponding to the stringified error if found.
1219 const errorObject = params['firebaseError']
1220 ? parseJsonOrNull(decodeURIComponent(params['firebaseError']))
1221 : null;
1222 const code = (_b = (_a = errorObject === null || errorObject === void 0 ? void 0 : errorObject['code']) === null || _a === void 0 ? void 0 : _a.split('auth/')) === null || _b === void 0 ? void 0 : _b[1];
1223 const error = code ? _createError(code) : null;
1224 if (error) {
1225 return {
1226 type: partialEvent.type,
1227 eventId: partialEvent.eventId,
1228 tenantId: partialEvent.tenantId,
1229 error,
1230 urlResponse: null,
1231 sessionId: null,
1232 postBody: null
1233 };
1234 }
1235 else {
1236 return {
1237 type: partialEvent.type,
1238 eventId: partialEvent.eventId,
1239 tenantId: partialEvent.tenantId,
1240 sessionId: partialEvent.sessionId,
1241 urlResponse: callbackUrl,
1242 postBody: null
1243 };
1244 }
1245 }
1246 return null;
1247}
1248function generateSessionId() {
1249 const chars = [];
1250 const allowedChars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
1251 for (let i = 0; i < SESSION_ID_LENGTH; i++) {
1252 const idx = Math.floor(Math.random() * allowedChars.length);
1253 chars.push(allowedChars.charAt(idx));
1254 }
1255 return chars.join('');
1256}
1257function storage() {
1258 return _getInstance(browserLocalPersistence);
1259}
1260function persistenceKey(auth) {
1261 return _persistenceKeyName("authEvent" /* AUTH_EVENT */, auth.config.apiKey, auth.name);
1262}
1263function parseJsonOrNull(json) {
1264 try {
1265 return JSON.parse(json);
1266 }
1267 catch (e) {
1268 return null;
1269 }
1270}
1271// Exported for testing
1272function _getDeepLinkFromCallback(url) {
1273 const params = searchParamsOrEmpty(url);
1274 const link = params['link'] ? decodeURIComponent(params['link']) : undefined;
1275 // Double link case (automatic redirect)
1276 const doubleDeepLink = searchParamsOrEmpty(link)['link'];
1277 // iOS custom scheme links.
1278 const iOSDeepLink = params['deep_link_id']
1279 ? decodeURIComponent(params['deep_link_id'])
1280 : undefined;
1281 const iOSDoubleDeepLink = searchParamsOrEmpty(iOSDeepLink)['link'];
1282 return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
1283}
1284/**
1285 * Optimistically tries to get search params from a string, or else returns an
1286 * empty search params object.
1287 */
1288function searchParamsOrEmpty(url) {
1289 if (!(url === null || url === void 0 ? void 0 : url.includes('?'))) {
1290 return {};
1291 }
1292 const [_, ...rest] = url.split('?');
1293 return querystringDecode(rest.join('?'));
1294}
1295
1296/**
1297 * @license
1298 * Copyright 2021 Google LLC
1299 *
1300 * Licensed under the Apache License, Version 2.0 (the "License");
1301 * you may not use this file except in compliance with the License.
1302 * You may obtain a copy of the License at
1303 *
1304 * http://www.apache.org/licenses/LICENSE-2.0
1305 *
1306 * Unless required by applicable law or agreed to in writing, software
1307 * distributed under the License is distributed on an "AS IS" BASIS,
1308 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1309 * See the License for the specific language governing permissions and
1310 * limitations under the License.
1311 */
1312/**
1313 * How long to wait for the initial auth event before concluding no
1314 * redirect pending
1315 */
1316const INITIAL_EVENT_TIMEOUT_MS = 500;
1317class CordovaPopupRedirectResolver {
1318 constructor() {
1319 this._redirectPersistence = browserSessionPersistence;
1320 this._shouldInitProactively = true; // This is lightweight for Cordova
1321 this.eventManagers = new Map();
1322 this.originValidationPromises = {};
1323 this._completeRedirectFn = _getRedirectResult;
1324 this._overrideRedirectResult = _overrideRedirectResult;
1325 }
1326 async _initialize(auth) {
1327 const key = auth._key();
1328 let manager = this.eventManagers.get(key);
1329 if (!manager) {
1330 manager = new CordovaAuthEventManager(auth);
1331 this.eventManagers.set(key, manager);
1332 this.attachCallbackListeners(auth, manager);
1333 }
1334 return manager;
1335 }
1336 _openPopup(auth) {
1337 _fail(auth, "operation-not-supported-in-this-environment" /* OPERATION_NOT_SUPPORTED */);
1338 }
1339 async _openRedirect(auth, provider, authType, eventId) {
1340 _checkCordovaConfiguration(auth);
1341 const manager = await this._initialize(auth);
1342 await manager.initialized();
1343 // Reset the persisted redirect states. This does not matter on Web where
1344 // the redirect always blows away application state entirely. On Cordova,
1345 // the app maintains control flow through the redirect.
1346 manager.resetRedirect();
1347 _clearRedirectOutcomes();
1348 await this._originValidation(auth);
1349 const event = _generateNewEvent(auth, authType, eventId);
1350 await _savePartialEvent(auth, event);
1351 const url = await _generateHandlerUrl(auth, event, provider);
1352 const iabRef = await _performRedirect(url);
1353 return _waitForAppResume(auth, manager, iabRef);
1354 }
1355 _isIframeWebStorageSupported(_auth, _cb) {
1356 throw new Error('Method not implemented.');
1357 }
1358 _originValidation(auth) {
1359 const key = auth._key();
1360 if (!this.originValidationPromises[key]) {
1361 this.originValidationPromises[key] = _validateOrigin(auth);
1362 }
1363 return this.originValidationPromises[key];
1364 }
1365 attachCallbackListeners(auth, manager) {
1366 // Get the global plugins
1367 const { universalLinks, handleOpenURL, BuildInfo } = _cordovaWindow();
1368 const noEventTimeout = setTimeout(async () => {
1369 // We didn't see that initial event. Clear any pending object and
1370 // dispatch no event
1371 await _getAndRemoveEvent(auth);
1372 manager.onEvent(generateNoEvent());
1373 }, INITIAL_EVENT_TIMEOUT_MS);
1374 const universalLinksCb = async (eventData) => {
1375 // We have an event so we can clear the no event timeout
1376 clearTimeout(noEventTimeout);
1377 const partialEvent = await _getAndRemoveEvent(auth);
1378 let finalEvent = null;
1379 if (partialEvent && (eventData === null || eventData === void 0 ? void 0 : eventData['url'])) {
1380 finalEvent = _eventFromPartialAndUrl(partialEvent, eventData['url']);
1381 }
1382 // If finalEvent is never filled, trigger with no event
1383 manager.onEvent(finalEvent || generateNoEvent());
1384 };
1385 // Universal links subscriber doesn't exist for iOS, so we need to check
1386 if (typeof universalLinks !== 'undefined' &&
1387 typeof universalLinks.subscribe === 'function') {
1388 universalLinks.subscribe(null, universalLinksCb);
1389 }
1390 // iOS 7 or 8 custom URL schemes.
1391 // This is also the current default behavior for iOS 9+.
1392 // For this to work, cordova-plugin-customurlscheme needs to be installed.
1393 // https://github.com/EddyVerbruggen/Custom-URL-scheme
1394 // Do not overwrite the existing developer's URL handler.
1395 const existingHandleOpenURL = handleOpenURL;
1396 const packagePrefix = `${BuildInfo.packageName.toLowerCase()}://`;
1397 _cordovaWindow().handleOpenURL = async (url) => {
1398 if (url.toLowerCase().startsWith(packagePrefix)) {
1399 // We want this intentionally to float
1400 // eslint-disable-next-line @typescript-eslint/no-floating-promises
1401 universalLinksCb({ url });
1402 }
1403 // Call the developer's handler if it is present.
1404 if (typeof existingHandleOpenURL === 'function') {
1405 try {
1406 existingHandleOpenURL(url);
1407 }
1408 catch (e) {
1409 // This is a developer error. Don't stop the flow of the SDK.
1410 console.error(e);
1411 }
1412 }
1413 };
1414 }
1415}
1416/**
1417 * An implementation of {@link PopupRedirectResolver} suitable for Cordova
1418 * based applications.
1419 *
1420 * @public
1421 */
1422const cordovaPopupRedirectResolver = CordovaPopupRedirectResolver;
1423function generateNoEvent() {
1424 return {
1425 type: "unknown" /* UNKNOWN */,
1426 eventId: null,
1427 sessionId: null,
1428 urlResponse: null,
1429 postBody: null,
1430 tenantId: null,
1431 error: _createError("no-auth-event" /* NO_AUTH_EVENT */)
1432 };
1433}
1434
1435/**
1436 * @license
1437 * Copyright 2017 Google LLC
1438 *
1439 * Licensed under the Apache License, Version 2.0 (the "License");
1440 * you may not use this file except in compliance with the License.
1441 * You may obtain a copy of the License at
1442 *
1443 * http://www.apache.org/licenses/LICENSE-2.0
1444 *
1445 * Unless required by applicable law or agreed to in writing, software
1446 * distributed under the License is distributed on an "AS IS" BASIS,
1447 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1448 * See the License for the specific language governing permissions and
1449 * limitations under the License.
1450 */
1451// This function should only be called by frameworks (e.g. FirebaseUI-web) to log their usage.
1452// It is not intended for direct use by developer apps. NO jsdoc here to intentionally leave it out
1453// of autogenerated documentation pages to reduce accidental misuse.
1454function addFrameworkForLogging(auth, framework) {
1455 _castAuth(auth)._logFramework(framework);
1456}
1457
1458export { AuthPopup, _generateEventId, _getRedirectResult, _overrideRedirectResult, addFrameworkForLogging, cordovaPopupRedirectResolver };
1459//# sourceMappingURL=internal.js.map