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: <token>
发出请求的客户端应用提供的 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 和更多 Cloud 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?