5

I'm playing with Callable HTTPS-functions in iOS. I've created and deployed the following function:

export const generateLoginToken = functions.https.onCall((data, context) => {

    const uid = data.user_id
    if (!(typeof uid === 'string') || uid.length === 0) {
        throw new functions.https.HttpsError('invalid-argument', 'The function must be called with one argument "user_id" ');
    }

    admin.auth().createCustomToken(uid)
    .then((token) => {
        console.log("Did create custom token:", token)
        return { text: "some_data" };
    }).catch((error) => {
        console.log("Error creating custom token:", error)
        throw new functions.https.HttpsError('internal', 'createCustomToken(uid) has failed for some reason')
    })
})

Then I call the function from my iOS-app like this:

let callParameters = ["user_id": userId]
    self?.functions.httpsCallable("generateLoginToken").call(callParameters) { [weak self] (result, error) in
    if let localError = self?.makeCallableFunctionError(error) {
        single(SingleEvent.error(localError))
    } else {
        print("Result", result)
        print("data", result?.data)
        if let text = (result?.data as? [String: Any])?["text"] as? String {
            single(SingleEvent.success(text))
        } else {
            let error = NSError.init(domain: "CallableFunctionError", code: 3, userInfo: ["info": "didn't find custom access token in the returned result"])
            single(SingleEvent.error(error))
        }
    }
}

I can see on the logs that the function is invoked on the server with the right parameters, but I can't seem to the get data that is being returned from the function back into the app. It seems that the result.data value is nilfor some reason, even though I return {text: "some_data"} from the cloud function. How come?

4
  • 1
    Can you show the code of your Function? Commented Apr 24, 2018 at 15:09
  • Also, what do you get if you call your Function via a browser? Commented Apr 24, 2018 at 15:13
  • You could be doing something wrong in your function code. Without seeing it, there's no way to tell. Commented Apr 24, 2018 at 20:38
  • Sorry.. I've added the cloud function :) It's an onCall function, I don't know how I would call it via a browser. When I try to paste the URL directly into an browser or do curl from the terminal, I get {"error":{"status":"INVALID_ARGUMENT","message":"Bad Request"}}. Commented Apr 24, 2018 at 21:00

1 Answer 1

5

Yikes! The issue was that I forgot to return the actual promise from the cloud function. This function is working:

export const generateLoginToken = functions.https.onCall((data, context) => {

    const uid = data.user_id
    if (!(typeof uid === 'string') || uid.length === 0) {
        throw new functions.https.HttpsError('invalid-argument', 'The function must be called with one argument "user_id" ');
    }

    return admin.auth().createCustomToken(uid)
    .then((token) => {
        console.log("Did create custom token:", token)
        return { text: "some_data" };
    }).catch((error) => {
        console.log("Error creating custom token:", error)
        throw new functions.https.HttpsError('internal', 'createCustomToken(uid) has failed for some reason')
    })
})
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for making me double check. For future reference: returning inside of a regular callback does NOT work. Must use promises.
Is there any additional steps other than adding this function to index.js? I copied it then deployed it "firebase deploy" through terminal but I get this error "Parsing error: 'import' and 'export' may appear only with 'sourceType: module' "
Hmm.. Yes, there are a few other steps. You need to initialize the admin SDK with your service account key. You should probably find a tutorial for how to make the "createCustomToken" work. Here's how I do: justpaste.it/57hqz . And then I deploy with "firebase deploy --only functions". Also follow this link, it's should cover the basics: firebase.google.com/docs/functions/get-started

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.