来自 Flutter App 的 Firebase Id Token 未在 REST 服务器上验证

Posted

技术标签:

【中文标题】来自 Flutter App 的 Firebase Id Token 未在 REST 服务器上验证【英文标题】:Firebase Id Token from Flutter App is not verified on the REST server 【发布时间】:2020-04-10 11:05:29 【问题描述】:

我想通过 Firebase 身份验证支持社交登录。但我想将用户的详细资料保存在我自己的 RDB 中。 我认为在用户使用社交帐户登录后,我可以获得包含用户 ID 和电子邮件的编码令牌。 然后,如果我将令牌发送到 REST 服务器(我使用 spring boot 构建它),那么服务器可以对其进行解码以从 RDB 加载用户的详细配置文件。

我按照本文中的指南进行操作。 https://blog.codemagic.io/firebase-authentication-google-sign-in-using-flutter/

我可以看到登录过程已成功完成,并且在控制台上打印了 id 令牌。 颤振(飞镖)代码如下。

final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;

final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);

final AuthResult authResult = await _auth.signInWithCredential(credential);
final FirebaseUser user = authResult.user;
name = user.displayName;
email = user.email;
imageUrl = user.photoUrl;
final FirebaseUser currentUser = await _auth.currentUser();
await currentUser.getIdToken().then((value) => print(value.token));

我将令牌复制到服务器模块中以测试它是否可以毫无问题地解码。 我添加了 firebase-admin 依赖项。并使用下面的 java 代码运行它。

FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.getApplicationDefault())
.setDatabaseUrl("https://test-firebase-auth-token.firebaseio.com")
.build();
FirebaseApp.initializeApp(options);

String firebaseToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImQ1OThkYjVjZ..."; // actually it's long string.

FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(firebaseToken);
System.out.println(decodedToken.getUid());
System.out.println(decodedToken.getEmail());

我得到了一个错误。

Exception in thread "main" com.google.firebase.auth.FirebaseAuthException: Failed to verify the signature of Firebase ID token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
    at com.google.firebase.auth.FirebaseTokenVerifierImpl.checkSignature(FirebaseTokenVerifierImpl.java:154)
    at com.google.firebase.auth.FirebaseTokenVerifierImpl.verifyToken(FirebaseTokenVerifierImpl.java:92)
    at com.google.firebase.auth.FirebaseAuth$4.execute(FirebaseAuth.java:426)
    at com.google.firebase.auth.FirebaseAuth$4.execute(FirebaseAuth.java:423)
    at com.google.firebase.internal.CallableOperation.call(CallableOperation.java:36)
    at com.google.firebase.auth.FirebaseAuth.verifyIdToken(FirebaseAuth.java:388)
    at com.google.firebase.auth.FirebaseAuth.verifyIdToken(FirebaseAuth.java:362)
    at com.example.demo.DemoApplicationTests.main(DemoApplicationTests.java:36)

我再次尝试使用 firebase-server-sdk 依赖项而不是 firebase-admin。 我收到了另一条错误消息。 (似乎与上述错误信息的原因相同)

Caused by: com.google.firebase.auth.FirebaseAuthException: Token isn't signed by a valid public key
    at com.google.firebase.auth.internal.FirebaseTokenVerifier.verifyTokenAndSignature(FirebaseTokenVerifier.java:61)
    at com.google.firebase.auth.FirebaseAuth$1.call(FirebaseAuth.java:146)
    at com.google.firebase.auth.FirebaseAuth$1.call(FirebaseAuth.java:140)
    at com.google.firebase.tasks.Tasks$1.run(Tasks.java:63)

我检查了这个网站上的令牌。 https://jwt.io/

我想知道令牌真的是用(私人)密钥签署的吗? 那么 jwt.io 站点如何在不知道密钥的情况下进行解码呢?

似乎它只是用像base64这样的开放算法编码的。不是吗? 如果是这样...令牌不再安全。

我的应用程序有什么问题。还是我对安全有误解? 任何评论都将受到欢迎。谢谢...

【问题讨论】:

你的代码应该没问题。请仔细检查flutter项目和spring是否在同一个firebase项目中。 感谢您的评论大声笑。我在客户端(颤振)和服务器(java)之间测试了不同的firebase项目。并收到另一条错误消息。 com.google.firebase.auth.FirebaseAuthException: Token is not for this app 此消息暗示 Flutter 和 java 应用程序配置为在第一次测试中看到相同的 firebase 项目。 我在 Flutter 应用程序中遇到了同样的问题,但在 Web 中没有。谷歌的公钥中似乎缺少解码的孩子。 【参考方案1】:

正如here 的回答,打印方法有问题。它仅限于 ~1024 个符号。

你可以这样打印:

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

【讨论】:

以上是关于来自 Flutter App 的 Firebase Id Token 未在 REST 服务器上验证的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:如何显示来自 Firebase 的文本?

Flutter, FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - 调用 Firebase App.ini

如何在 Flutter 中缓存来自 Firebase 的图像?

Flutter(Firebase)约会应用,来自同一集合的文档之间的关系

Flutter 中来自 Firebase 的应用检查不起作用

Flutter Web - Firebase:没有创建 Firebase App '[DEFAULT]' - 调用 Firebase App.initializeApp() (app/no-app)