Laravel Firebase Admin SDK无法验证Flutter谷歌登录Token
问题概述
无法通过Kreait Laravel Firebase Admin SDK验证Flutter端谷歌登录用户的Token,两种传递场景均报错:
- 传递谷歌登录的
accessToken时,提示Token不是有效的JWT(缺少两个点) - 传递谷歌登录的
idToken时,提示Token发行者和受众不被后端Firebase SDK认可
后端验证代码
public static function verifyIdToken(string $idToken): array { $firebase = Firebase::auth(); $firebaseClaims = $firebase->verifyIdToken($idToken)->claims()->all(); if ($firebaseClaims['email'] == null) { return [ "message" => "Invalid User, try another email address", ]; } return $firebaseClaims; }
错误响应
传递accessToken时
{ "message": "The value 'ya29.a0AeDClZBN...' is not a verified ID token:\n- The token is invalidThe JWT string must have two dots\n", "exception": "Kreait\Firebase\Exception\Auth\FailedToVerifyToken", "file": "/Users/name/projects/backend/socialitclub/vendor/kreait/firebase-php/src/Firebase/Auth.php", "line": 402 }
传递idToken时
{ "message": "The value 'eyJhbGciOiJSUzI...' is not a verified ID token:\n- The token was not issued by the given issuers\n- The token is not allowed to be used by this audience\n", "exception": "Kreait\Firebase\Exception\Auth\FailedToVerifyToken", "file": "/Users/name/projects/backend/project/vendor/kreait/firebase-php/src/Firebase/Auth.php", "line": 402 }
前端Flutter代码
Future<String?> initiateSignInAndGetToken() async { // TODO: For testing purpose await _googleSignIn.signOut(); final googleUser = await _googleSignIn.signIn(); final googleAuth = await googleUser?.authentication; // Note the accessToken that I pass to backend is not valid, and I have also tried to send IdToken instead final token = googleAuth?.accessToken; return token; }
错误原因分析
- accessToken验证失败:
verifyIdToken方法仅支持验证Firebase发行的ID Token(JWT格式),而谷歌登录返回的accessToken是OAuth2访问令牌,并非JWT,自然无法通过校验。 - idToken验证失败:前端获取的是谷歌原生ID Token,而非Firebase Auth生成的ID Token,导致其发行者(
iss)和受众(aud)与后端Firebase项目配置不匹配。
解决方案
方案1:前端获取Firebase兼容的ID Token(推荐)
在Flutter中集成Firebase Auth,通过Firebase登录流程获取标准的Firebase ID Token,后端可直接用verifyIdToken验证:
import 'package:firebase_auth/firebase_auth.dart'; import 'package:google_sign_in/google_sign_in.dart'; Future<String?> initiateSignInAndGetFirebaseIdToken() async { final GoogleSignIn _googleSignIn = GoogleSignIn(); await _googleSignIn.signOut(); final GoogleSignInAccount? googleUser = await _googleSignIn.signIn(); if (googleUser == null) return null; final GoogleSignInAuthentication googleAuth = await googleUser.authentication; final OAuthCredential credential = GoogleAuthProvider.credential( accessToken: googleAuth.accessToken, idToken: googleAuth.idToken, ); // 通过Firebase Auth完成登录 final UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(credential); final User? user = userCredential.user; // 获取Firebase ID Token return await user?.getIdToken(); }
方案2:后端调整验证逻辑,直接校验谷歌accessToken
若不想集成Firebase Auth,后端可调用谷歌官方的Token验证接口来校验accessToken:
use GuzzleHttp\Client; public static function verifyGoogleAccessToken(string $accessToken): array { $client = new Client(); try { $response = $client->get('https://www.googleapis.com/oauth2/v3/tokeninfo', [ 'query' => ['access_token' => $accessToken] ]); $data = json_decode($response->getBody(), true); if (empty($data['email'])) { return [ "message" => "Invalid User, try another email address", ]; } return $data; } catch (\Exception $e) { return [ "message" => "Invalid access token: " . $e->getMessage(), ]; } }
方案3:修复Firebase ID Token的发行者/受众不匹配问题
若坚持使用Firebase的verifyIdToken,需确保:
- 前端谷歌登录使用的客户端ID,与Firebase项目中添加的OAuth客户端ID完全一致
- 后端Firebase Admin SDK使用的服务账号密钥,属于当前验证的Firebase项目
- 解析前端传递的idToken,确认
iss字段为https://securetoken.google.com/<你的Firebase项目ID>,aud字段为你的Firebase项目ID
内容的提问来源于stack exchange,提问作者Rakshith Gajendra
相关产品推荐
相关产品推荐

