Skip to content

Callable function returns 'Unauthenticated' error when using the functions emulator #7783

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
maxim04 opened this issue Mar 24, 2021 · 11 comments · Fixed by #8258
Closed

Callable function returns 'Unauthenticated' error when using the functions emulator #7783

maxim04 opened this issue Mar 24, 2021 · 11 comments · Fixed by #8258

Comments

@maxim04
Copy link

maxim04 commented Mar 24, 2021

[REQUIRED] Step 1: Describe your environment

  • Xcode version: 12.4
  • Firebase SDK version: FirebaseFunctions (7.8.0)
  • Installation method: CocoaPods
  • Firebase Component: Functions

[REQUIRED] Step 2: Describe the problem

When using the emulator for functions and calling a callable function from the app, the request immediately returns an error: Unauthenticated, there are no logs from the emulator when the error is returned so i am guessing the request doesn't even reach the function.

Steps to reproduce:

  1. Start emulators
  2. Start ios app with emulators configured
  3. call the callable function

Actual result: fails with error: Unauthenticated.

Expected result: The callable function is executed successfully.

Relevant Code:

(Swift)

Auth.auth().useEmulator(withHost:"localhost", port:9099)
Functions.functions().useEmulator(withHost: "localhost", port: 5001)

Functions.functions().httpsCallable("functionName").call(functionData) { (result, error) in }

The code above fails with the following details:
error.code: __C.FIRFunctionsErrorCode,
error.localizedDescription: Unauthenticated

@google-oss-bot
Copy link

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@maxim04 maxim04 changed the title Callable function returns error when using the functions emulator Callable function returns 'Unauthenticated' error when using the functions emulator Mar 24, 2021
@rizafran
Copy link
Contributor

Thanks for reporting, @maxim04. This might be a permission issue. First off, make sure that you're running the latest CLI version. Also, It seems like the suggested steps here may fix the Unauthenticated error. Make sure as well that you're the owner of the project. Let me know of your findings.

@maxim04
Copy link
Author

maxim04 commented Mar 25, 2021

@rizafran I am running the latest firebase cli 9.7.0. The suggestion in the provided link to "Allowing unauthenticated function invocation" is not my goal here. I want the function to be called with authentication.

Some more info:

  • I am the owner of the project in firebase
  • I have all the necessary rights.
  • Everything works as expected in production mode.
  • The problem arises when using the emulator.

I have a function setup as follows:

import * as functions from 'firebase-functions';

export const myFunction = functions
    .https
    .onCall(async (data, context) => {
        ...
    });

The iOS app can call the function successfully when the function runs in the cloud. The problem arises when running the functions emulator. When using the functions emulator and the iOS app calls the function using (swift code) functions.httpsCallable("functionName").call(functionData) { ... } the call fails with the Unauthenticated error.

@morganchen12
Copy link
Contributor

@samtstern do you know what could be going on here?

@samtstern
Copy link
Contributor

@maxim04 sounds like it might be a Firebase CLI issue. Could you run the Firebase emulators emulators:start with the --debug flag and then show the logs when this issue happens?

@maxim04
Copy link
Author

maxim04 commented Mar 30, 2021

@samtstern started the simulators with the debug flag and unfortunately there was no log output when the error occurs. I did however enabled debug logging for firebase using -FIRDebugEnabled xcode flag and when the
Functions.functions().httpsCallable("myFunction").call(functionData) { (result, error) in } is called the following line is printed to console:
7.8.0 - [Firebase/Auth][I-AUT000017] Has valid access token. Estimated expiration date: 2021-03-30 10:17:08 +0000, current date: 2021-03-30 09:20:25 +0000
In the callback the error property has the following value:
Error Domain=com.firebase.functions Code=16 "Unauthenticated" UserInfo={NSLocalizedDescription=Unauthenticated}.

Is there anything else i can do to show additional logging?

@samtstern
Copy link
Contributor

unfortunately there was no log output when the error occurs.

There has to be some output though, right? Can you show all of the debug logs from a run when this error occurs? Don't worry if you don't see any error in the logs.

@maxim04
Copy link
Author

maxim04 commented Mar 31, 2021

@samtstern After further investigation I found that even though in the iOS app I configure the functions to use the emulator like so Functions.functions().useEmulator(withHost: "localhost", port: 5001) when the line Functions.functions().httpsCallable("myFunction") is executed, it makes a call to the real function in the cloud, it does not use the function running in the emulator. This is confirmed by the following log from the cloud functions: Function execution took 629 ms, finished with status code: 401. This explains why i didn't see any logs in the emulator and why i am getting the Unauthenticated error in the app when the user logs in using the emulator authentication and when the function is called, the call is made to the real function and because the auth session is different i get a 401.

So it looks like the issue is in the ios sdk where it doesn't use the functions emulator when it is configured.

@morganchen12
Copy link
Contributor

@maxim04 can you enable debug logging and share the logs from Xcode when your app is running?

@maxim04
Copy link
Author

maxim04 commented Mar 31, 2021

@morganchen12 here is the output from xcode with debug logging enabled:

2021-03-31 23:41:46.669977+0100 EmulatorFunctionTest[29873:264493] 7.8.0 - [Firebase/Core][I-COR000001] Configuring the default app.
2021-03-31 23:41:46.670533+0100 EmulatorFunctionTest[29873:264493] 7.8.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001008] Successfully created App Delegate Proxy automatically. To disable the proxy, set the flag GoogleUtilitiesAppDelegateProxyEnabled to NO (Boolean) in the Info.plist
23:41:46.675 💚 DEBUG EmulatorFunctionTestApp.application():57 - no user signed in
2021-03-31 23:41:46.754208+0100 EmulatorFunctionTest[29873:264494] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed
2021-03-31 23:41:46.754539+0100 EmulatorFunctionTest[29873:264494] [connection] nw_socket_handle_socket_event [C1.1:2] Socket SO_ERROR [61: Connection refused]
2021-03-31 23:41:46.759148+0100 EmulatorFunctionTest[29873:264504] 7.8.0 - [GoogleUtilities/SceneDelegateSwizzler][I-SWZ001114] Successfully created Scene Delegate Proxy automatically. To disable the proxy, set the flag GoogleUtilitiesAppDelegateProxyEnabled to NO (Boolean) in the Info.plist
2021-03-31 23:41:46.759910+0100 EmulatorFunctionTest[29873:264503] 7.8.0 - [Firebase/Auth][I-AUT000017] Has valid access token. Estimated expiration date: 2021-03-31 23:41:46 +0000, current date: 2021-03-31 22:41:46 +0000
2021-03-31 23:41:46.760113+0100 EmulatorFunctionTest[29873:264503] 7.8.0 - [Firebase/Core][I-COR000033] Data Collection flag is not set.
2021-03-31 23:41:46.788151+0100 EmulatorFunctionTest[29873:264494] [connection] nw_socket_handle_socket_event [C2.1:2] Socket SO_ERROR [61: Connection refused]
23:41:46.817 💚 DEBUG EmulatorFunctionTestApp.application():62 - signed in successfuly
23:41:49.197 💚 DEBUG ContentView.callFunc():29 - calling function
2021-03-31 23:41:49.197536+0100 EmulatorFunctionTest[29873:264504] 7.8.0 - [Firebase/Auth][I-AUT000002] Token auto-refresh enabled.
2021-03-31 23:41:49.197690+0100 EmulatorFunctionTest[29873:264504] 7.8.0 - [Firebase/Auth][I-AUT000004] Token auto-refresh scheduled in 54:58 for the new token.
2021-03-31 23:41:49.197837+0100 EmulatorFunctionTest[29873:264504] 7.8.0 - [Firebase/Auth][I-AUT000017] Has valid access token. Estimated expiration date: 2021-03-31 23:41:46 +0000, current date: 2021-03-31 22:41:49 +0000
23:41:49.462 ❤️ ERROR ContentView.callFunc():37 - Optional(__C.FIRFunctionsErrorCode)
23:41:49.462 ❤️ ERROR ContentView.callFunc():38 - Unauthenticated
23:41:49.462 ❤️ ERROR ContentView.callFunc():39 - nil

@anthonyliuhao
Copy link

I had the same issue. If I do this, I get the same Unauthenticated error.

Functions.functions().useEmulator(withHost: "localhost", port: 5001)
Functions.functions().httpsCallable("functionName").call(functionData) { (result, error) in }

However, the following works.

let functions = Functions.functions()
functions.useEmulator(withHost: "localhost", port: 5001)
functions.httpsCallable("functionName").call(functionData) { (result, error) in }

I don't understand the source code, but it looks like Functions.functions() returns an instance of the Functions class, which is the client for interacting with Cloud Functions. Just my theory.

This is weird because you can configure Firebase Auth by calling Auth.auth().useEmulator(withHost:"localhost", port:9099) for the entire client app.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants