Firebase Functions AppCheck 不断让我的设备失败

Posted

技术标签:

【中文标题】Firebase Functions AppCheck 不断让我的设备失败【英文标题】:Firebase Functions AppCheck keeps failing my device 【发布时间】:2021-10-16 16:18:38 【问题描述】:

我一直在尝试将 AppCheck 与我的 android 应用程序集成,但我似乎无法发出有效的请求。

出于测试目的,我一直在使用以下代码:

Android 代码

class Application : MultiDexApplication() 

    override fun onCreate() 
        FirebaseApp.initializeApp(this)

        val appCheck = FirebaseAppCheck.getInstance()
        if (BuildConfig.DEBUG) appCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance(), true)
        else appCheck.installAppCheckProviderFactory(SafetyNetAppCheckProviderFactory.getInstance(), true)

        super.onCreate()
    


class TestActivity : Activity() 

    override fun onCreate(savedInstanceState: Bundle?) 
        val data = "This is a test!"
        Firebase.functions.getHttpsCallable("test").call(data).addOnCompleteListener 
            if (it.isSuccessful) 
                val result = it.result.data
                print(result)
            

            else 
                val exception = it.exception
                print(exception)
            
        
    

功能代码

const functions = require("firebase-functions")

exports.test = functions.https.onCall((data, context) => 
  if (context.app == undefined) 
    functions.logger.error("Test - Failed validating device integrity!")
    throw new functions.https.HttpsError("failed-precondition", "The function must be called from an App Check verified app")
  

  return data
)

我已将 DebugAppCheckProviderFactory 令牌添加到 Firebase 控制台,但无论我做什么,如果它是模拟器或物理设备,当我调用该函数时,failed-precondition 总是抛出异常。

查看函数日志,我可以看到应用程序丢失了:

我已经多次阅读文档,而且我似乎没有遗漏任何步骤。我是否遗漏了什么,或者我能做些什么来找到它的根本原因?

感谢您的宝贵时间!

编辑:

至于 Martin 的建议,我创建了一个新的 OnRequest 函数并添加了 X-Firebase-AppCheck 标头。我正确收到了令牌,并且能够通过以下方式成功验证它:

firebaseAdmin.appCheck().verifyToken(appCheckToken)

所以,我的猜测是 Android 并没有像应有的那样将 X-Firebase-AppCheck 自动添加到 OnCall 函数中。

我运行代码并通过代码设置了一些断点并注意到以下内容。 Firebase 的 call 方法正在添加 Firebase-Instance-ID-Token 但我似乎找不到 X-Firebase-AppCheck任何地方的标题。也许我不应该看到这个值,或者我只是找不到它被添加的位置。或者它根本没有添加,因此我根本无法验证我的 context.app

【问题讨论】:

【参考方案1】:

可能需要获取AppCheckToken

FirebaseAppCheck
        .getInstance()
        .getAppCheckToken(false)
        .addOnSuccessListener(new OnSuccessListener<AppCheckToken>() 
            @Override
            public void onSuccess(@NonNull AppCheckToken tokenResponse) 

                String appCheckToken = tokenResponse.getToken();
                ...
            
        );

必须与 HTTP 请求一起传递(示例显示 Retrofit,也可以使用它来代替 HttpsCallable

@GET("yourExampleEndpoint")
Call<List<String>> exampleData(
    @Header("X-Firebase-AppCheck") String appCheckToken,
    ...
);

FirebaseFunctions.getInstance().getHttpsCallable().call() 没有说明如何或是否必须明确设置 X-Firebase-AppCheck 标头。 Cloud Functions 通常应该收到一个 X-Firebase-AppCheck 标头 - 带有之前检索到的 AppCheck 令牌:

const appCheckToken = req.header('X-Firebase-AppCheck');

if (!appCheckToken) 
    res.status(401);
    return next('Unauthorized');


try 
    const appCheckClaims = await firebaseAdmin.appCheck().verifyToken(appCheckToken);
    // If verifyToken() succeeds, continue with the next middleware function in the stack.
    return next();
 catch (err) 
    res.status(401);
    return next('Unauthorized');

也可以发行自己的令牌...checking for context-app 也是有效的。


更新:Protocol specification for https.onCall 内容如下:

可选:X-Firebase-AppCheck: &lt;token&gt; 发出请求的客户端应用提供的 Firebase 应用检查令牌。后端自动验证此令牌并对其进行解码,将 appId 注入处理程序的上下文中。如果无法验证令牌,则拒绝请求。适用于 SDK >=3.14.0

安装所需的最低 NodeJS 依赖项:

npm install firebase-functions@">=3.14.0"
npm install firebase-admin@">=9.8.0"

最后但并非最不重要的......甚至还有一个调试助手:

dependencies 
    debugImplementation "com.google.firebase:firebase-appcheck-debug:16.0.0-beta02"

【讨论】:

非常感谢@Martin 的回复。我试图在 SuccessListener 之后运行该函数,结果是一样的。我可以看到“appCheckToken”值,但 context.app 仍然丢失。至于标题,我没有 req 和 res 值。当我使用 OnCall 函数时,我有数据和上下文。有没有办法从这两个值中检查标题? 这是可用的:firebase.google.com/docs/functions/callable-reference ...添加 LogCat 和更多 Clo​​ud Logging,以查看实际发送和接收的 HTTP 标头。事实证明,一次只能在HTTP funciton 内访问标题;如果HttpsCallable 不会以某种方式附加该X-Firebase-AppCheck 标头,则它可能与预期用途不兼容-除非这会提供context.app(因为标头已被抽象掉)。 确保 SDK >=3.14.0,标头应附加到HttpsCallable 我创建了一个新的 OnRequest 并尝试使用 firebaseAdmin.appCheck().verifyToken 验证令牌。似乎它能够以这种方式验证令牌。看来我的 OnCall 功能是这里的问题。我将仔细检查 SDK 版本,并会尽快更新或发表评论。非常感谢您抽出宝贵时间@Martin! 更新了 firebase-functions 和 firebase-admin 但在 OnCall 函数中仍然存在同样的问题。【参考方案2】:

在测试一切都没有成功后,我绝望地尝试查找不相关的文件并找到了解决方案。

在我的 build.gradle 中,我正在使用 bom 导入所有 Firebase 依赖项:

implementation platform("com.google.firebase:firebase-bom:27.0.0")
implementation "com.google.firebase:firebase-crashlytics-ktx"
implementation "com.google.firebase:firebase-analytics-ktx"
implementation "com.google.firebase:firebase-firestore-ktx"
implementation "com.google.firebase:firebase-functions-ktx"
implementation "com.google.firebase:firebase-auth-ktx"

所以我想:“firebase-bom 可以导入过时的 functions-ktx 依赖项吗?”

你猜怎么着?一旦我导入了没有 bom 的依赖项,我就开始看到添加了 X-Firebase-AppCheck 并且 context.app 有效。

我最终得到了以下 build.grade

implementation "com.google.firebase:firebase-crashlytics-ktx:18.2.1"
implementation "com.google.firebase:firebase-analytics-ktx:19.0.0"
implementation "com.google.firebase:firebase-firestore-ktx:23.0.3"
implementation "com.google.firebase:firebase-functions-ktx:20.0.0"
implementation "com.google.firebase:firebase-auth-ktx:21.0.1"

经过一番调查,我发现我使用的是过时的 firebase-bom 版本。 Android Studio 曾经让我知道依赖项是否有新版本,但它没有注意到 firebase-bom。事实证明,我只需要更新我的 firebase-bom 依赖项。

TL;DR

检查您的 Android Firebase 库版本!

【讨论】:

以上是关于Firebase Functions AppCheck 不断让我的设备失败的主要内容,如果未能解决你的问题,请参考以下文章

部署 firebase 项目时错误显示“找不到模块 firebase-functions”

无法在 razorpay [firebase_functions/internal] 内部的 firebase 云函数中创建订单 ID

Firebase-tools 升级后 Firebase-functions 身份验证失败

如何处理 Firebase Cloud Functions 中的错误 JSON?

Firebase Cloud Functions 访问 Firebase 托管文件

Firebase Cloud Functions https.onCall 完成状态码:204