1--- 2title: Using Firebase 3--- 4 5import { Terminal } from '~/ui/components/Snippet'; 6 7[Firebase](https://firebase.google.com/) gives you functionality like analytics, databases, messaging and crash reporting so you can move quickly and focus on your users. Firebase is built on Google infrastructure and scales automatically, for even the largest apps. 8 9> This guide uses `[email protected]`. As of SDK 43, the Expo SDK no longer enforces or recommends any specific version of Firebase to use in your app. If you are using an older version of the `firebase` library in your project you may have to adapt the code examples below to match the version that you are using, with the help of the [Firebase JS SDK documentation](https://github.com/firebase/firebase-js-sdk). 10 11## Usage with Expo Go 12 13If you'd like to use Firebase in the Expo Go app, we recommend using the [Firebase JS SDK](https://github.com/firebase/firebase-js-sdk). It supports Authentication, Firestore & Realtime databases, Storage, and Functions on React Native. Other modules like Analytics are [not supported through the Firebase JS SDK](https://firebase.google.com/support/guides/environments_js-sdk), but you can use [`expo-firebase-analytics`](/versions/latest/sdk/firebase-analytics) for that. 14 15If you'd like access to the full suite of native firebase tools, we recommend using the [React Native Firebase](https://rnfirebase.io/#expo) with a [development build](/development/introduction). React Native Firebase is not supported in the [Expo Go](https://expo.dev/expo-go) app. 16 17> **Note:** This guide mostly covers Firebase Realtime Database (and some Firestore as well). For more background on why some Firebase services are not supported, please refer to the ["What goes into the Expo SDK?" FYI page](https://expo.fyi/whats-in-the-sdk). 18 19## Firebase SDK Setup 20 21First we need to setup a Firebase Account and create a new project. We will be using the JavaScript SDK provided by Firebase, so pull it into your Expo project. 22 23<Terminal cmd={['$ npx expo install firebase']} /> 24 25[Firebase Console](http://console.firebase.google.com/) provides you with an API key, and other identifiers for your project needed for initialization. [firebase-web-start](https://firebase.google.com/docs/database/web/start) has a detailed description of what each field means and where to find them in your console. 26 27```javascript 28import { initializeApp } from 'firebase/app'; 29 30// Optionally import the services that you want to use 31//import {...} from "firebase/auth"; 32//import {...} from "firebase/database"; 33//import {...} from "firebase/firestore"; 34//import {...} from "firebase/functions"; 35//import {...} from "firebase/storage"; 36 37// Initialize Firebase 38const firebaseConfig = { 39 apiKey: 'api-key', 40 authDomain: 'project-id.firebaseapp.com', 41 databaseURL: 'https://project-id.firebaseio.com', 42 projectId: 'project-id', 43 storageBucket: 'project-id.appspot.com', 44 messagingSenderId: 'sender-id', 45 appId: 'app-id', 46 measurementId: 'G-measurement-id', 47}; 48 49let myApp = initializeApp(firebaseConfig); 50``` 51 52### Temporarily Bypass Default Security Rules 53 54By default Firebase Realtime Database (RTDB) has a security rule setup such that all devices accessing your data must be authenticated. We obviously haven't setup any authentication yet, so we can disable it for now while we setup the rest of our app. 55 56Go into Firebase Console >> _Realtime Database_, and under the Rules tab you should see a default set of rules already provided for you. Change the rules to: 57 58```javascript 59{ 60 "rules": { 61 ".read": true, 62 ".write": true 63 } 64} 65``` 66 67[See Sample RTDB Rules](https://firebase.google.com/docs/database/security/quickstart#sample-rules) for good sets of rules for your data, including unauthenticated. 68 69> **Note** It is important to note that this is temporary for development, and these rules should be thoroughly assessed before releasing an application. 70 71## Storing Data and Receiving Updates 72 73Storing data through Firebase RTDB is pretty simple. Imagine we're creating a game where highscores are stored in RTDB for everyone to see. We could create a `users` bucket that is referenced by each user. Setting their highscore is straightforward: 74 75```javascript 76import { getDatabase, ref, onValue, set } from 'firebase/database'; 77 78function storeHighScore(userId, score) { 79 const db = getDatabase(); 80 const reference = ref(db, 'users/' + userId); 81 set(reference, { 82 highscore: score, 83 }); 84} 85``` 86 87Now let's say we want another client to listen to updates to the high score of a specific user. Firebase allows us to set a listener on a specific data reference and get notified each time there is an update to the data. In the example below, every time a highscore is updated for the given user, it will print it to console. 88 89```javascript 90import { getDatabase, ref, onValue } from 'firebase/database'; 91 92setupHighscoreListener(userId) { 93 const db = getDatabase(); 94 const reference = ref(db, 'users/' + userId); 95 onValue(reference, (snapshot) => { 96 const highscore = snapshot.val().highscore; 97 console.log("New high score: " + highscore); 98 }); 99} 100``` 101 102## User Authentication 103 104This was all pretty simple and works fairly out of the box for what Firebase JavaScript SDK provides. There is one caveat however. We skipped the authentication rules for simplicity at the beginning. Firebase SDKs provide authentication methods for developers, so they don't have to reimplement common login systems such as Google or Facebook login. 105 106This includes UI elements in the Web, Android, and iOS SDK versions for Firebase, however, these UI components do not work with React Native and **should not** be called. Thankfully, Firebase gives us ways to authenticate our data access given that we provide user authentication ourselves. 107 108### Login Methods 109 110We can choose different login methods that make sense to our application. The login method choice is orthogonal to the Firebase RTDB access, however, we do need to let Firebase know how we have setup our login system so that it can correctly assign authentication tokens that match our user accounts for data access control. You can use anything you want, roll your own custom login system, or even forego it altogether if all your users can have unrestricted access - though unrestricted access is strongly discouraged and instead Firebase recommends using their [_Anonymous_ authentication provider](https://firebase.google.com/docs/auth/web/anonymous-auth). 111 112### Facebook Login 113 114{/* TODO: Mention third-party facebook packages */} 115 116A common login system many developers opt for is a simple Facebook login that users are already familiar with. 117 118See the Facebook section of our docs for information on how to set this up. This works just as well with Google and [several others](<https://firebase.google.com/docs/reference/android/com/google/firebase/auth/AuthCredential#getProvider()>). 119 120### Tying Sign-In Providers with Firebase 121 122Once you have added Facebook login to your React Native app, we need to adjust the Firebase console to check for it. Go to [Firebase Console](http://console.firebase.google.com/) >> _Authentication_ >> _Sign-In method_ tab to enable Facebook as a sign-in provider. 123 124You can add whichever provider makes sense for you, or even add multiple providers. 125 126### Phone Authentication 127 128To use phone authentication, you'll need the `expo-firebase-recaptcha` package. It provides a reCAPTCHA widget which is necessary to verify that you are not a bot. 129 130Please follow the instructions for the [expo-firebase-recaptcha](/versions/latest/sdk/firebase-recaptcha) package on how to use phone auth. 131 132### Re-enable Data Access Security Rule 133 134We need to re-enable the Data Security Rule in Firebase Console again to check for user authentication. This time our rules will be slightly more complicated. 135 136For our example, let's say we want everyone to be able to read the high score for any user, but we want to restrict writes to only the user who the score belongs to. You wouldn't want anyone overwriting your highscore, would you? 137 138```javascript 139{ 140 "rules": { 141 "users": { 142 "$uid": { 143 ".read": true, 144 ".write": "$uid === auth.uid" 145 } 146 } 147 } 148} 149``` 150 151### Listening for Authentication 152 153We are now ready to connect the Facebook login code in our app with our Firebase Realtime Database implementation. 154 155```javascript 156import { initializeApp } from 'firebase/app'; 157import { 158 getAuth, 159 onAuthStateChanged, 160 FacebookAuthProvider, 161 signInWithCredential, 162} from 'firebase/auth'; 163import * as Facebook from 'expo-facebook'; 164 165let myApp = initializeApp(config); 166 167const auth = getAuth(myApp); 168 169// Listen for authentication state to change. 170onAuthStateChanged(auth, user => { 171 if (user != null) { 172 console.log('We are authenticated now!'); 173 } 174 175 // Do other things 176}); 177 178async function loginWithFacebook() { 179 await Facebook.initializeAsync('<FACEBOOK_APP_ID>'); 180 181 const { type, token } = await Facebook.logInWithReadPermissionsAsync({ 182 permissions: ['public_profile'], 183 }); 184 185 if (type === 'success') { 186 // Build Firebase credential with the Facebook access token. 187 const facebookAuthProvider = new FacebookAuthProvider(); 188 const credential = facebookAuthProvider.credential(token); 189 190 // Sign in with credential from the Facebook user. 191 signInWithCredential(auth, credential).catch(error => { 192 // Handle Errors here. 193 }); 194 } 195} 196``` 197 198The Facebook login method is similar to what you see in the Facebook login guide, however, the token we receive from a successful login can be passed to the Firebase SDK to provide us with a Firebase credential via `FacebookAuthProvider.credential`. We can then sign-in with this credential via `signInWithCredential`. 199 200The `onAuthStateChanged` event allows us to set a listener when the authentication state has changed, so in our case, when the Facebook credential is used to successfully sign in to Firebase, we are given a user object that can be used for authenticated data access. 201 202### Authenticated Data Updates with Firebase Realtime Database 203 204Now that we have a user object for our authenticated user, we can adapt our previous `storeHighScore()` method to use the uid of the user object as our user reference. Since the `user.uid`'s are generated by Firebase automatically for authenticated users, this is a good way to reference our users bucket. 205 206```javascript 207import { getDatabase, ref, set } from 'firebase/database'; 208 209function storeHighScore(user, score) { 210 if (user != null) { 211 const database = getDatabase(); 212 set(ref(db, 'users/' + user.uid), { 213 highscore: score, 214 }); 215 } 216} 217``` 218 219## Using Expo with Firestore 220 221[Firestore](https://firebase.google.com/docs/firestore/) a second database service in Firebase, the other being Realtime Database. Realtime Database can be thought of as a "JSON tree in the cloud" where your app can listen to and modify different portions of the tree. On the other hand, Firestore is a "document store" database. Your application will store and retrieve entire "documents" at a time, where a "document" is essentially a JavaScript object. Each have their advantages, and sometimes applications will end up using both. See [the comparison chart](https://firebase.google.com/docs/firestore/rtdb-vs-firestore) and [take the survey](https://firebase.google.com/docs/firestore/rtdb-vs-firestore#key_considerations). 222 223Here's is an example of storing a document named "mario" inside of a collection named "characters" in Firestore: 224 225```javascript 226import { initializeApp } from 'firebase/app'; 227import { getFirestore, setDoc, doc } from 'firebase/firestore'; 228 229const firebaseConfig = { ... } // apiKey, authDomain, etc. (see above) 230 231let myApp = initializeApp(firebaseConfig); 232 233const firestore = getFirestore(myApp); 234 235await setDoc(doc(firestore, "characters", "mario"), { 236 employment: "plumber", 237 outfitColor: "red", 238 specialAttack: "fireball" 239}); 240``` 241 242This sample was borrowed and edited from [this forum post](https://forums.expo.dev/t/open-when-an-expo-firebase-firestore-platform/4126/29). 243 244## Recording events with Analytics 245 246In order to record analytics events, the Expo Firebase Core and Analytics packages needs to be installed. 247 248<Terminal cmd={['$ npx expo install expo-firebase-analytics']} /> 249 250This package uses a JavaScript-based implementation in Expo Go, and the native Firebase SDK everywhere else. 251 252To configure native Firebase, please follow the configuration instructions for the [`expo-firebase-analytics`](/versions/latest/sdk/firebase-analytics) package. 253 254```javascript 255import * as Analytics from 'expo-firebase-analytics'; 256 257Analytics.logEvent('hero_spotted', { 258 hero_name: 'Saitama', 259}); 260``` 261