UNPKG

@react-native-firebase/app-check

Version:

React Native Firebase - App Check

244 lines (212 loc) 7.71 kB
/* * Copyright (c) 2016-present Invertase Limited & Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this library except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import { isBoolean, isIOS, isString, isObject, isFunction, isUndefined, isOther, } from '@react-native-firebase/app/lib/common'; import { createModuleNamespace, FirebaseModule, getFirebaseRoot, } from '@react-native-firebase/app/lib/internal'; import { Platform } from 'react-native'; import ReactNativeFirebaseAppCheckProvider from './ReactNativeFirebaseAppCheckProvider'; import { setReactNativeModule } from '@react-native-firebase/app/lib/internal/nativeModule'; import fallBackModule from './web/RNFBAppCheckModule'; import version from './version'; const namespace = 'appCheck'; const nativeModuleName = 'RNFBAppCheckModule'; export class CustomProvider { constructor(_customProviderOptions) { if (!isObject(_customProviderOptions)) { throw new Error('Invalid configuration: no provider options defined.'); } if (!isFunction(_customProviderOptions.getToken)) { throw new Error('Invalid configuration: no getToken function defined.'); } this._customProviderOptions = _customProviderOptions; } async getToken() { return this._customProviderOptions.getToken(); } } const statics = { CustomProvider, }; class FirebaseAppCheckModule extends FirebaseModule { constructor(...args) { super(...args); this.emitter.addListener(this.eventNameForApp('appCheck_token_changed'), event => { this.emitter.emit(this.eventNameForApp('onAppCheckTokenChanged'), event); }); this._listenerCount = 0; } getIsTokenRefreshEnabledDefault() { // no default to start isTokenAutoRefreshEnabled = undefined; return isTokenAutoRefreshEnabled; } newReactNativeFirebaseAppCheckProvider() { return new ReactNativeFirebaseAppCheckProvider(); } initializeAppCheck(options) { if (isOther) { if (!isObject(options)) { throw new Error('Invalid configuration: no options defined.'); } if (isUndefined(options.provider)) { throw new Error('Invalid configuration: no provider defined.'); } return this.native.initializeAppCheck(options); } // determine token refresh setting, if not specified if (!isBoolean(options.isTokenAutoRefreshEnabled)) { options.isTokenAutoRefreshEnabled = this.firebaseJson.app_check_token_auto_refresh; } // If that was not defined, attempt to use app-wide data collection setting per docs: if (!isBoolean(options.isTokenAutoRefreshEnabled)) { options.isTokenAutoRefreshEnabled = this.firebaseJson.app_data_collection_default_enabled; } // If that also was not defined, the default is documented as true. if (!isBoolean(options.isTokenAutoRefreshEnabled)) { options.isTokenAutoRefreshEnabled = true; } this.native.setTokenAutoRefreshEnabled(options.isTokenAutoRefreshEnabled); if (options.provider === undefined || options.provider.providerOptions === undefined) { throw new Error('Invalid configuration: no provider or no provider options defined.'); } if (Platform.OS === 'android') { if (!isString(options.provider.providerOptions.android.provider)) { throw new Error( 'Invalid configuration: no android provider configured while on android platform.', ); } return this.native.configureProvider( options.provider.providerOptions.android.provider, options.provider.providerOptions.android.debugToken, ); } if (Platform.OS === 'ios' || Platform.OS === 'macos') { if (!isString(options.provider.providerOptions.apple.provider)) { throw new Error( 'Invalid configuration: no apple provider configured while on apple platform.', ); } return this.native.configureProvider( options.provider.providerOptions.apple.provider, options.provider.providerOptions.apple.debugToken, ); } throw new Error('Unsupported platform: ' + Platform.OS); } activate(siteKeyOrProvider, isTokenAutoRefreshEnabled) { if (isOther) { throw new Error('firebase.appCheck().activate(*) is not supported on other platforms'); } if (!isString(siteKeyOrProvider)) { throw new Error('siteKeyOrProvider must be a string value to match firebase-js-sdk API'); } // We wrap our new flexible interface, with compatible defaults rnfbProvider = new ReactNativeFirebaseAppCheckProvider(); rnfbProvider.configure({ android: { provider: 'playIntegrity', }, apple: { provider: 'deviceCheck', }, web: { provider: 'reCaptchaV3', siteKey: 'none', }, }); return this.initializeAppCheck({ provider: rnfbProvider, isTokenAutoRefreshEnabled }); } // TODO this is an async call setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled) { this.native.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled); } getToken(forceRefresh) { if (!forceRefresh) { return this.native.getToken(false); } else { return this.native.getToken(true); } } getLimitedUseToken() { return this.native.getLimitedUseToken(); } _parseListener(listenerOrObserver) { return typeof listenerOrObserver === 'object' ? listenerOrObserver.next.bind(listenerOrObserver) : listenerOrObserver; } // eslint-disable-next-line @typescript-eslint/no-unused-vars onTokenChanged(onNextOrObserver, onError, onCompletion) { // iOS does not provide any native listening feature if (isIOS) { // eslint-disable-next-line no-console console.warn('onTokenChanged is not implemented on IOS, only for Android'); return () => {}; } const nextFn = this._parseListener(onNextOrObserver); // let errorFn = function () { }; // if (onNextOrObserver.error != null) { // errorFn = onNextOrObserver.error.bind(onNextOrObserver); // } // else if (onError) { // errorFn = onError; // } const subscription = this.emitter.addListener( this.eventNameForApp('onAppCheckTokenChanged'), nextFn, ); if (this._listenerCount === 0) this.native.addAppCheckListener(); this._listenerCount++; return () => { subscription.remove(); this._listenerCount--; if (this._listenerCount === 0) this.native.removeAppCheckListener(); }; } } // import { SDK_VERSION } from '@react-native-firebase/app-check'; export const SDK_VERSION = version; // import appCheck from '@react-native-firebase/app-check'; // appCheck().X(...); export default createModuleNamespace({ statics, version, namespace, nativeModuleName, nativeEvents: ['appCheck_token_changed'], hasMultiAppSupport: true, hasCustomUrlOrRegionSupport: false, ModuleClass: FirebaseAppCheckModule, }); export * from './modular'; // import appCheck, { firebase } from '@react-native-firebase/app-check'; // appCheck().X(...); // firebase.appCheck().X(...); export const firebase = getFirebaseRoot(); // Register the interop module for non-native platforms. setReactNativeModule(nativeModuleName, fallBackModule);