4

I am trying to enforce firebase app-check for my android app. Specifically, I want to restrict access to my firebase cloud functions written in python. I found instructions on how to do this on node.js based firebase cloud functions, but none for Python. I'm using the firebase_admin module. The module has a verify_token function firebase_admin.app_check.verify_token(token: str, app=None), however I don't see where I am getting the token from in my HTTP Flask-based cloud function.

I define my cloud function like this:

def my_cloud_function(request):
    ....

Is the app-check token supposed to be somewhere in the request header or arguments? Is this documented in some place that I missed?

Nik
  • 1,093
  • 7
  • 26
  • 1
    Ok I see, I create a Firebase App Check token by using the App Check SDK in my client application and pass that token as a header in the request that I make to the Cloud Function. Then I use the `verify_token` function to check that token in Python. – Nik May 08 '23 at 07:49
  • It sounds like you found the answer yourself @Nik. --- Can you post that below with the relevant code for both the client and the server? That way others can benefit from your findings, and the system knows that you've been helped. – Frank van Puffelen May 08 '23 at 13:50

2 Answers2

1

Now that Cloud Functions for Firebase has public preview support for Python (just announced at I/O 23!), you can protect callable functions with App Check just as in the Node guide that you shared:

from firebase_functions import https_fn


@https_fn.on_call(
    # Requests with invalid App Check tokens will be rejected with HTTP error 401.
    enforce_app_check=true
)
def my_api(request: https_fn.CallableRequest) -> Any:
    """
    request.app will be undefined if the request doesn't include an
    App Check token.
    """
    if request.app is None:
        raise https_fn.HttpsError(
            code=https_fn.FunctionsErrorCode.FAILED_PRECONDITION,
            message=("The function must be called from an App Check verified app."),
        )

    # Function logic ...
Jeff
  • 2,425
  • 1
  • 18
  • 43
0

I will explain how to check the AppCheck token in Firebase Cloud Functions and call Cloud Functions by putting the AppCheck token in the header in the app as follows.

Flutter App, FirebaseAppCheck Token in the header and call Cloud Functions.

final appCheckToken = await FirebaseAppCheck.instance.getToken();
if (appCheckToken != null) {
    final response = await http.get(
        Uri.parse("https://<Cloud Functions URI>/?text=addmessage3app"),
        headers: {"X-Firebase-AppCheck": appCheckToken},
    );
    print('test');
} else {
    // Error: couldn't get an App Check token.
}

Firebase Cloud Functions Backend (in Python)

  • In @https_fn.on_request, set enforce_app_check=True.
  • Get the token of X-Firebase-AppCheck from header and verify_token from app_check.
  • verify_token in app_check and call
  • If no exception is thrown, ok

Here is the code.

from firebase_admin import app_check
import jwt

@https_fn.on_request(
    # Requests with invalid App Check tokens will be rejected with HTTP error 401.
    enforce_app_check=True
)
def my_api3(req: https_fn.Request) -> https_fn.Response:
    app_check_token = req.headers.get("X-Firebase-AppCheck", default="")
    try:
        app_check_claims = app_check.verify_token(app_check_token)
        # If verify_token() succeeds, okay to continue to route handler.
    except (ValueError, jwt.exceptions.DecodeError):
        return https_fn.Response("Not verified", status=401)

    # my code
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided",  status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add(
        {"original": original}
    )

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added!")

Test, I added the FirebaseAppCheck token in Flutter and checked that CloudFunctions works properly, and conversely, when I called it without FirebaseAppCheck token in Flutter App, I checked that the 401 error code I defined is responded.

I used PostMan to test CloudFunctions by reusing the token I created and used in FlutterApp. See the attached picture.enter image description hereenter image description here

alones
  • 2,848
  • 2
  • 27
  • 30