Flutter Firebase Auth - PHP 服务器中的令牌验证问题

Posted

技术标签:

【中文标题】Flutter Firebase Auth - PHP 服务器中的令牌验证问题【英文标题】:Flutter Firebase Auth - Token verification problem in PHP server 【发布时间】:2021-02-06 03:42:06 【问题描述】:

我在我的 Flutter 应用中使用 Firebase 身份验证来管理用户(Facebook、Google、电子邮件...)。当用户登录我的应用程序时,我将 Firebase 令牌发送到我的 php 服务器,在该服务器上使用 JWT 验证该令牌。

问题是,虽然通过电子邮件登录生成的令牌已正确验证,但 Facebook 或 Google 登录生成的令牌失败并显示“SignatureInvalidException:签名验证失败”。

Flutter 应用中的 Facebook 登录代码:

FirebaseAuth auth = FirebaseAuth.instance;
final LoginResult result = await FacebookAuth.instance.login();

final FacebookAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(result.accessToken.token);
UserCredential user = await auth.signInWithCredential(facebookAuthCredential);

String token = await auth.currentUser.getIdToken();
print(token.toString());

在https://jwt.io/调试器中正确验证了token的信息,所以header和payload都没问题。

在 PHP 服务器中(两种情况下的代码相同):

验证电子邮件和密码令牌(OK):

stdClass 对象([iss] => https://securetoken.google.com/project-123546 [aud] => project-123546 [auth_time] => 1603424825 [user_id] => S2gpfdsa156dsacdsfQ2z1 [sub] => S2gpfdsa156dsacdsfQ2z1 [iat] => [56034248 exp] => 1603428425 [email] => user@example.com [email_verified] => [firebase] => stdClass Object ( [identities] => stdClass Object ( [email] => Array ( [0] => user@ example.com ) ) [sign_in_provider] => 密码 ) )

验证 Facebook 令牌 (KO):

致命错误:未捕获的 Firebase\JWT\SignatureInvalidException:签名验证在 server\vendor\firebase\php-jwt\src\JWT.php:122 中失败 堆栈跟踪:#0 server\token.php(18) : Firebase\JWT\JWT::decode('eygswbdsasdJSUzI...', '-----BEGIN CERT...', Array) #1 main 在 server\vendor\firebase\php-jwt\src 中抛出\JWT.php 在第 122 行

PHP 代码:

$token = "...TOKEN-FROM-APP...";
$pkeys_raw = file_get_contents('https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com');
$pkeys = json_decode($pkeys_raw, true);
$decoded = JWT::decode($token, $pkeys, ["RS256"]);
print_r($decoded);

KeyID 与 https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com 中的密钥匹配,但我认为应用程序(或 Firebase)未使用 Facebook 和 Google 登录中的私钥正确签署令牌。不过我在邮箱和密码登录也是用auth.currentUser.getIdToken(),所以没有区别。

知道如何解决这个问题吗?

【问题讨论】:

【参考方案1】:

研究 Flutter 的 firebase 库后,我找到了这个问题的答案。我在这里发布它以防万一它对某人有帮助。

库很好,签名正确生成。 原因与库完全无关——android 平台上 Flutter/Dart 中的 debugPrint() 没有足够的缓冲区来打印出整个令牌字符串。 所以问题出在print(token.toString());,如果您将令牌发送到服务器,它将被正确解码。

有关此问题的所有信息: https://github.com/FirebaseExtended/flutterfire/issues/2728

【讨论】:

【参考方案2】:

我认为你可以使用log 来获取整个令牌:

log(token);

即使 jwt 令牌从 https://jwt.io 以某种方式无效,但我仍然能够使用 Firebase Admin SDK 从我的 Java 后端验证它。

FirebaseAuth.getInstance(firebaseApp).verifyIdToken(token);

【讨论】:

【参考方案3】:

另外,你可以这样打印:

final idToken = await firebaseCredential.user!.getIdToken(true);
print(idToken.substring(0, 1000));
print(idToken.substring(1000));

【讨论】:

以上是关于Flutter Firebase Auth - PHP 服务器中的令牌验证问题的主要内容,如果未能解决你的问题,请参考以下文章

flutter-firebase_auth-gradlew.bat 异常退出

Flutter Firebase Auth 新更新 [重复]

Flutter Firebase auth facebook无法正常工作

Flutter 应用程序错误将尝试连接 Firebase 和 Auth

在 iOS 中使用 LinkedIn + firebase auth + Flutter 登录

Flutter - firebase_auth updateProfile 方法不起作用