在Dart中获取Google Cloud Logging访问令牌时遇OAuth客户端未找到错误
问题:获取Google OAuth2服务账号访问令牌时返回"invalid_client"错误
错误信息:
{
"error": "invalid_client",
"error_description": "The OAuth client was not found."
}
使用的Dart代码:
var jsonFile = await File(jsonPath).readAsString(); var map = jsonDecode(jsonFile); final jwt = JWT( { 'iss': map['client_email'], 'sub': map['client_email'], 'aud': map['token_uri'], 'iat': (DateTime.now().millisecondsSinceEpoch / 1000).floor(), 'exp': (DateTime.now().add(Duration(hours: 1)).millisecondsSinceEpoch / 1000) .floor(), }, issuer: map['private_key_id'], ); final token = jwt.sign(SecretKey(map['private_key'])); print(token); final accessToken = await http.post( Uri.parse(map['token_uri']), headers: { HttpHeaders.contentTypeHeader: 'application/x-www-form-urlencoded', }, body: { 'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion': token, }, );
可能的原因及修复方案
1. JWT的aud字段设置错误
Google OAuth2服务账号要求aud(受众)固定为https://oauth2.googleapis.com/token,而非凭据JSON中的token_uri字段值。误用token_uri会导致受众不匹配,触发身份验证错误。
修复:
将JWT payload中的'aud': map['token_uri'],替换为:
'aud': 'https://oauth2.googleapis.com/token',
2. JWT构造的issuer参数错误
初始化JWT时传入的issuer: map['private_key_id']是错误的,该参数应设置为服务账号邮箱(map['client_email']),或直接移除——因为payload中已经包含iss字段,重复设置错误值会导致Google无法识别客户端身份。
修复:
移除JWT构造中的issuer参数,或修正为正确值:
final jwt = JWT( { 'iss': map['client_email'], 'sub': map['client_email'], 'aud': 'https://oauth2.googleapis.com/token', 'iat': (DateTime.now().millisecondsSinceEpoch / 1000).floor(), 'exp': (DateTime.now().add(Duration(hours: 1)).millisecondsSinceEpoch / 1000) .floor(), }, // 移除该行,或改为 issuer: map['client_email'] );
3. 凭据文件类型错误
确保使用的是服务账号JSON密钥文件(包含type: "service_account"、client_email、private_key等字段),而非OAuth客户端ID凭据(含client_id、client_secret字段)。后者无法用于服务账号的JWT授权流程。
4. JWT签名算法不匹配
Google服务账号要求使用RS256算法签名,但代码中使用的SecretKey通常对应HS256算法,会导致签名无效。
修复:
改用RSA私钥签名,以dart_jwt库为例:
import 'package:jwt/jwt.dart'; import 'package:pointycastle/pointycastle.dart'; // 解析RSA私钥 final privateKey = RSAKeyParser().parse(map['private_key']) as RSAPrivateKey; // 使用RS256签名 final token = jwt.sign(RSAPrivateKeySigner(RSASignDigest.SHA256, privateKey));
5. 服务账号权限或API未启用
- 确认Cloud Logging API已在Google Cloud项目中启用;
- 检查服务账号的Logging Admin角色是否正确绑定(在IAM页面验证角色分配)。
内容的提问来源于stack exchange,提问作者neil_ruaro
相关产品推荐
相关产品推荐

