skip to Main Content

I am trying to connect with an iOS device to the Firebase Auth and RealTime Database Emulator.

The thing is, I can connect and use emulator through Firebase Admin using NodeJS on local machine (trough http://localhost:9000?ns=my-project).

Also I am able to connect with an iOS device to the remote Firebase server… But locally it doesn’t work. It throws bunch of random errors, like this (when I try to complete registration/authentication):

Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the
server." NSLocalizedDescription=Could not connect to the server.,
NSErrorFailingURLStringKey=http://192.168.1.3:9099/www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=myKeyGoesHere

and

Optional(Error Domain=com.firebase.core Code=1 "Unable to get latest
value for query FQuerySpec (path: /news, params: { }), client offline
with no active listeners and no matching disk cache entries"

Here is firebase.json:

{
  "database": {
    "rules": "database.rules.json"
  },
  "emulators": {
    "auth": {
      "port": 9099
    },
    "database": {
      "port": 9000
    },
    "ui": {
      "enabled": true
    }
  }
}

I changed rules just in case:

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

but its not that.

and here is how I try to connect to database in my iOS application(my FirebaseManager class):

 init(){
      Auth.auth().useEmulator(withHost:"192.168.1.3", port:9099)
 }

  private lazy var newsNodeRef:DatabaseReference? = {
    
    guard let urlString = getBaseURL() else {return nil}
    
    let node = LocalConstants.kNewsRef // this has value of 'news'
    return Database.database(url: urlString).reference(withPath: node)
}()


    
    private func getBaseURL()->String?{
        let environment = Environment()
        guard let connectionProtocol = environment.configuration(PlistKey.firebaseConnectionProtocol), let baseURL = environment.configuration(PlistKey.firebaseDatabaseURL) else {return nil}
        let urlString = "(connectionProtocol)://(baseURL)"
        
        return urlString // this produces something like 'http://192.168.1.3:9000?ns=my-project' (its fetched from Configuration Settings file based on selected environment)
    }

the thing is, the exact same setup works on remote server, if I just change the environment(which automatically changes base url).

I have also allowed insecure http loads in info.plist, just to be sure if it is not that, but still doesn’t work.

This is what I get in console when I run emulators:

terminal

What is the problem here?

3

Answers


  1. Chosen as BEST ANSWER

    I actually solved it. The solution/problem, I don't even know how to declare it, was with Local Network Access prompt & permissions and its buggy behaviour (as well how I was trying to access my Mac by ip).

    At first I didn't even see a prompt shows every time, but I guess it was related to a wrong setup of a port, host etc.

    But when I correctly set local computer's ip and reverted firebase.json to it's default settings (which is what worked for me), the prompt started to jump out every time.

    The thing is, prompt's behaviour seems broken, because instead of jumping before you try to access devices in a local network, it pops out after that action is made. Quite fast, but still after Auth system responded, which doesn't make sense.

    Here, it can be confusing, cause error that is returned from a Firebase Auth system in the case when you didn't allow Local Network Access usage, doesn't really tell you much about real cause. See my ( original question) above to see the errors.

    After that terrible flow, I allowed access trough the prompt. Once I did that, on every next 'api' call towards Emulator was successful. Worked like a charm.

    The real problem here is Local Network Access prompt. Cause we don't have at all control over it, so we can't that easily trigger it, or easily get info what user have selected/chosen at the moment / or before. It's triggered by the system in certain conditions.

    Luckily this is just for development :) but I hope it will be fixed/improved soon, cause it should.

    I found a lot about this topic and its considered as a bug Local Network Access Prompt problems on Dev portal:


  2. I was also faced the same problem while using the firebase auth in iOS simulator
    then i change my code little bit

    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      if (Platform.isAndroid) {
        await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
      }
    
      runApp(const MyApp());
    }
    

    I have made a check for only android and it works for me
    Inside this method you can see it only works for android.

    Login or Signup to reply.
  3. I replied a little late ๐Ÿ˜Š.
    I saw the solution you found. It didn’t work for me but I’m sure it has worked for a lot of people.

    I found a solution too.
    Actually, I couldn’t see a problem for iOS 15. My problem was that it didn’t work on iOS 14 and earlier.

    Solution;

    First, you need the MacBook’s IP address.
    To find the IP address;
    You can access it right under System preferences -> Network -> Status.

    Then we need to make some changes in the firebase.json file.

    Adding โ€œhostโ€ : โ€œIPโ€ for each part.
    Overwrite the โ€œhostโ€ part with the โ€œportโ€ part.

    "emulators": {
    "auth": {
      "host": "192.168.1.11โ€,
      "port": 9100
    },
    "functions": {
      "host": "192.168.1.11โ€,
      "port": 5002
    },
    "firestore": {
      "host": "192.168.1.11โ€,
      "port": 8081
    },
    "database": {
      "host": "192.168.1.11",
      "port": 9001
    },
    "storage": {
      "host": "192.168.1.11",
      "port": 9200
    },
    "ui": {
      "enabled": true
    }
    

    Then we need to add in swift codes.
    We need to write the IP address in the host part.
    More precisely, we will replace the parts that say localhost with the IP address.

    let settings = Firestore.firestore().settings
    settings.host = "192.168.1.11:8081"
    settings.isPersistenceEnabled = false
    settings.isSSLEnabled = false
    Firestore.firestore().settings = settings
        
    Storage.storage().useEmulator(withHost:"192.168.1.11", port:9200)
    Auth.auth().useEmulator(withHost:"192.168.1.11", port:9100)
    let db = Database.database(url:"http://192.168.1.11:9001?ns=firebaseappname")
    Functions.functions().useFunctionsEmulator(origin: "http://192.168.1.11:5002")
    

    I think this solution will work in JS, android and other languages.

    I would appreciate it if you tried this solution and let me know if it works.
    It worked for me.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search