首页 > 解决方案 > 来自 Flutter App 的 Firebase Id Token 未在 REST 服务器上验证

问题描述

我想通过 firebase auth 支持社交登录。但我想将用户的详细资料保存在我自己的 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这样的开放算法编码的。不是吗?如果是这样...令牌不再安全。

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

标签: firebaseauthenticationflutter

解决方案


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

你可以这样打印:

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

推荐阅读