Skip to content
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

Firebase Function unauthorized with iOS, works on emulator #14181

Open
reedm121 opened this issue Nov 27, 2024 · 1 comment
Open

Firebase Function unauthorized with iOS, works on emulator #14181

reedm121 opened this issue Nov 27, 2024 · 1 comment
Assignees

Comments

@reedm121
Copy link

reedm121 commented Nov 27, 2024

Description

Expected

I expect my helloWorld firebase function to execute when called from functions.httpsCallable("helloWorld").call() in my Swift code. I only want people who install my app to be able to use my function, so I'm not looking for the authenticate allUsers option.

It works as expected if I use firebase emulator and point my Swift code to the emulator and port:
Simulator Screen Recording - iPhone 16 - 2024-11-27 at 01 20 05

Actual result (using deployed Firebase function)

Whenever I move off the functions emulator to try and run it via the deployed Firebase functions, I get denied with a 401 Error and the following is the most informative part of the Google Cloud logs:
textPayload:"The request was not authorized to invoke this service. Read more at https://cloud.google.com/run/docs/securing/authenticating Additional troubleshooting documentation can be found at: https://cloud.google.com/run/docs/troubleshooting#401"

Here is how it looks running it on the simulator:
Simulator Screen Recording - iPhone 16 - 2024-11-27 at 01 29 03

My Code

helloWorld function

//index.js 
// containing my deployed Firebase function

const { onCall, onRequest } = require("firebase-functions/v2/https");
const logger = require("firebase-functions/logger");

exports.helloWorld = onCall((data, context) => {
    // Log the user's authentication status
    if (context.auth) {
        logger.info("User is authenticated:", context.auth.uid);
    } else {
        logger.info("User is not authenticated.");
    }

    return { message: "Hello World from Firebase function!" };
});

Swift files

//ContentView.swift
struct ContentView: View {
    @StateObject var firebaseFunctionsManager: FirebaseFunctionsManager = FirebaseFunctionsManager()
    
    @State var helloWorldMsg: String = "function not called yet"
    
    var body: some View {
        VStack {
            Button("Call hello world firebase function"){
                Task{
                    do{
                        print("⚪️ Attempting to call helloWorld...")
                        helloWorldMsg = try await firebaseFunctionsManager.callHelloWorld()
                    }
                    catch{
                        print("🔴 Error: \(error.localizedDescription)")
                        helloWorldMsg = error.localizedDescription
                    }
                }
            }.buttonStyle(.bordered)
            Text(helloWorldMsg)
            Button("Clear"){
                helloWorldMsg = ""
            }.buttonStyle(.bordered)
        }
        .padding()
    }
}

//FirebaseFunctionsManager.swift
class FirebaseFunctionsManager: ObservableObject {
    lazy var functions = Functions.functions()
    
    func callHelloWorld() async throws -> String {
        do {
            //functions.useEmulator(withHost: "localhost", port: 5001)
            let result = try await functions.httpsCallable("helloWorld").call()
            
            // Parse the response to extract the string message
            if let data = result.data as? [String: Any],
               let message = data["message"] as? String {
                return message
            } else {
                throw NSError(domain: "InvalidResponse", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unexpected response format."])
            }
        } catch {
            throw error
        }
    }
}

I even wondered if it was a Firebase authentication issue so I added anonymous authentication in my App init

//FirebaseFunctionsExampleApp.swift

@main
struct FirebaseFunctionsExampleApp: App {
    init() {
        FirebaseConfiguration.shared.setLoggerLevel(.debug)
        
        FirebaseApp.configure()
        
        // Authenticate Anonymously
        Auth.auth().signInAnonymously { authResult, error in
            if let error = error {
                print("🔴 Error signing in anonymously: \(error.localizedDescription)")
            } else if let user = authResult?.user {
                print("🟢 Signed in anonymously with user ID: \(user.uid)")
            }
        }
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

I've also tried messing with the IAM policies but nothing worked. And the more I look into the Authentication I keep reading that Firebase Functions are meant to handle authentication themselves. Or am I meant to be implementing from the guides here?

Reproducing the issue

  1. Make a firebase functions directory with firebase init
  2. Connect the directory to a firebase project with an iOS app
  3. Make a simple onCall function like helloWorld that sends some kind of data to be displayed to the iOS app
  4. Call the function from the iOS app

Firebase SDK Version

11.5

Xcode Version

16.1

Installation Method

Swift Package Manager

Firebase Product(s)

Functions

Targeted Platforms

iOS

Relevant Log Output

11.5.0 - [FirebaseCore][I-COR000001] Configuring the default app.
11.5.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001014] App Delegate does not conform to UIApplicationDelegate protocol.
11.5.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
🟢 Signed in anonymously with user ID: OUm3lIy1K9bUCusn85XMAEAtcVH3
11.5.0 - [FirebaseCore][I-COR000033] Data Collection flag is not set.
⚪️ Attempting to call helloWorld...
11.5.0 - [FirebaseAuth][I-AUT000002] Token auto-refresh enabled.
11.5.0 - [FirebaseAuth][I-AUT000004] Token auto-refresh scheduled in 14:48 for the new token.
11.5.0 - [FirebaseAuth][I-AUT000017] Has valid access token. Estimated expiration date:2024-11-27 06:13:08 +0000, current date: 2024-11-27 05:53:20 +0000
GTMSessionFetcher 0x10660f390 (https://us-central1-fir-functionsexample-1f77e.cloudfunctions.net/helloWorld) was already running
🔴 Error: UNAUTHENTICATED

If using Swift Package Manager, the project's Package.resolved

Expand Package.resolved snippet
Replace this line with the contents of your Package.resolved.

If using CocoaPods, the project's Podfile.lock

Expand Podfile.lock snippet
Replace this line with the contents of your Podfile.lock!
@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.

@reedm121 reedm121 changed the title Firebase Function unauthorized when using with iOS Firebase deployed Function unauthorized with iOS, works on emulator Nov 27, 2024
@reedm121 reedm121 changed the title Firebase deployed Function unauthorized with iOS, works on emulator Firebase Function unauthorized with iOS, works on emulator Nov 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants