Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase + React Native: Offline authentication

I'm using Firebase in a React Native iOS app, mainly for storing user data and user authentication, which works great when a device actually has a working network connection.

When it comes to Firebase's offline capabilities, it looks like this:

The problem: Users launching app without network connectivity can't do anything because they're never being logged in

Here are the steps to reproduce this behaviour:

Step 1: Logged-out user launches app with network connectivity

  1. user clicks "Facebook login" button
  2. Firebase logs in using Facebook auth
  3. onAuthStateChanged (user) is being called with the logged in user as parameter
  4. token obtained by user.getToken() is sent to my server, which generates a custom token (generatedToken) that can be used for signing into Firebase auth using signInWithCustomToken (generatedToken) and is therefore saved in local storage
  5. user happily reads and writes into Firebase database, changes are instantly synced with Firebase server

Step 2: Logged-in user launches app with network connectivity

  1. app realizes there's a generatedToken in local storage
  2. generatedToken is used for firebase.auth().signInWithCustomToken (..)
  3. (same as Step 1.3)
  4. (same as Step 1.4)
  5. (same as Step 1.5)
  6. Network connectivity gets lost: User is still logged in (onAuthStateChanged (user) is not being called with null as a user, like it's the case after manually signing out) and can therefore still read & write into Firebase database
  7. Network connectivity gets restored: Changes sync with Firebase server

Step 3: Logged-in user launches app without network connectivity

  1. app realizes there's a generatedToken in local storage
  2. generatedToken is used for firebase.auth().signInWithCustomToken (..)
  3. firebase.auth().signInWithCustomToken (..) fails, because there's not network connection
  4. onAuthStateChanged (user) is being called with null as a user
  5. user is not able to use Firebase database at all, since all read/write requests fails because of missing authentication

The attempted solution

  1. Setting persistenceEnabled to true in Objective-C / AppDelegate.m, right after initializing FIRApp:

    (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      // ...
      [FIRApp configure];
      [FIRDatabase database].persistenceEnabled = YES;
      // ...
    }
    

    This doesn't lead to the desired result and (at least in my case) doesn't change anything when it comes to Firebase's behaviour.

  2. --- YOUR SUGGESTION HERE ---

Thanks for your inputs!

like image 702
skizzo Avatar asked Jan 27 '17 13:01

skizzo


People also ask

Does Firebase Auth work offline?

Persistence BehaviorBy enabling persistence, any data that the Firebase Realtime Database client would sync while online persists to disk and is available offline, even when the user or operating system restarts the app. This means your app works as it would online by using the local data stored in the cache.

How do I use react native offline?

To have offline-first functionality when the app is launched and there is no connection, you will need to add redux-persist to your app. This enables it to store a snapshot of the state of your app to the device's memory and rehydrate the state when the app is launched.


1 Answers

Whilst the Firebase JS SDK is great and does generally work in React Native, it is mainly built for web platforms and therefore is not the most comprehensive solution for usage inside a React Native environment e.g. there are quite a few Firebase services you'll be unable to use with the Web SDK. See the comparison table here.

You can, however, run with the native Android/iOS Firebase SDKs and have a bridge between them and your JavaScript code (i.e. a react native module).

Thankfully you don't have to implement this yourself, as there are already modules out there to do this for you:

react-native-firebase for example mirrors the web SDKs API on the JavaScript side but executes on the native side using the native Android & iOS Firebase SDKs. It's compatible with any existing Firebase Web SDK logic that you may have already implemented and is intended as a drop-in replacement for the web SDK.

This library supports your use case with auth persistence and offline capabilities:

import firebase from 'react-native-firebase';

const instance = firebase.initializeApp({
  persistence: true
});

// can also use `keepSynced` / `setPersistence` methods:
// instance.database().ref('/someref').keepSynced();
// instance.database().setPersistence(true);

export default instance;

(disclaimer: I am the author of react-native-firebase)

like image 67
Salakar Avatar answered Sep 29 '22 01:09

Salakar