在Salesforce调用Google Document AI遇OAuth令牌错误,求配置及方案
解决Salesforce调用Google Document AI的认证问题
一、正确配置Named Credentials解决"No_Oauth_Token"错误
你的Scope https://www.googleapis.com/auth/cloud-platform 是正确的,该错误通常来自配置细节问题,按以下步骤检查并修正:
Google Cloud OAuth客户端配置
- 创建Web应用类型的OAuth 2.0客户端ID,回调URL必须严格匹配Salesforce格式:
https://<你的Salesforce实例域名>/services/authcallback/<你的Named Credentials API名称> - 确保客户端ID、客户端密钥无拼写错误,且已在Google Cloud控制台启用Document AI API。
- 创建Web应用类型的OAuth 2.0客户端ID,回调URL必须严格匹配Salesforce格式:
Salesforce Named Credentials配置
- 认证类型选择
OAuth 2.0,认证流程选择Authorization Code - Scope字段填入
https://www.googleapis.com/auth/cloud-platform - 勾选「Start Authentication Flow on Save」,保存后完成授权跳转流程
- 注意:Sandbox环境需使用对应Sandbox域名,回调URL不可混用生产环境域名
- 认证类型选择
二、其他获取Google OAuth令牌的方式
1. 服务账号JWT认证(推荐生产环境使用)
适合无用户交互的服务器端调用,步骤如下:
- 在Google Cloud创建服务账号,分配
Document AI Processor User角色,下载JSON密钥文件 - 在Salesforce中通过Apex生成JWT并请求令牌,示例代码:
public class GoogleTokenGenerator { public static String getServiceAccountToken() { // 替换为你的服务账号密钥JSON内容 String serviceAccountJson = '{"type":"service_account","project_id":"YOUR_PROJECT_ID","private_key_id":"YOUR_KEY_ID","private_key":"-----BEGIN PRIVATE KEY-----\nYOUR_PRIVATE_KEY\n-----END PRIVATE KEY-----\n","client_email":"YOUR_SERVICE_ACCOUNT_EMAIL","client_id":"YOUR_CLIENT_ID","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"YOUR_CERT_URL"}'; Map<String, Object> saData = (Map<String, Object>)JSON.deserializeUntyped(serviceAccountJson); String clientEmail = (String)saData.get('client_email'); String privateKey = (String)saData.get('private_key'); String tokenUri = (String)saData.get('token_uri'); // 构建JWT头部 Map<String, String> header = new Map<String, String>(); header.put('alg', 'RS256'); header.put('typ', 'JWT'); String encodedHeader = EncodingUtil.base64Encode(JSON.serialize(header).getBytes('UTF-8')).replace('+', '-').replace('/', '_').replace('=', ''); // 构建JWT payload Long now = DateTime.now().getTime() / 1000; Map<String, Object> payload = new Map<String, Object>(); payload.put('iss', clientEmail); payload.put('scope', 'https://www.googleapis.com/auth/cloud-platform'); payload.put('aud', tokenUri); payload.put('exp', now + 3600); // 令牌有效期1小时 payload.put('iat', now); String encodedPayload = EncodingUtil.base64Encode(JSON.serialize(payload).getBytes('UTF-8')).replace('+', '-').replace('/', '_').replace('=', ''); // 签名JWT String signatureInput = encodedHeader + '.' + encodedPayload; Blob privateKeyBlob = EncodingUtil.base64Decode(privateKey.replace('-----BEGIN PRIVATE KEY-----\n', '').replace('\n-----END PRIVATE KEY-----', '')); Blob signature = Crypto.sign('RSA-SHA256', Blob.valueOf(signatureInput), privateKeyBlob); String encodedSignature = EncodingUtil.base64Encode(signature).replace('+', '-').replace('/', '_').replace('=', ''); String jwt = encodedHeader + '.' + encodedPayload + '.' + encodedSignature; // 请求访问令牌 HttpRequest req = new HttpRequest(); req.setEndpoint(tokenUri); req.setMethod('POST'); req.setHeader('Content-Type', 'application/x-www-form-urlencoded'); req.setBody('grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=' + EncodingUtil.urlEncode(jwt, 'UTF-8')); Http http = new Http(); HttpResponse res = http.send(req); if (res.getStatusCode() == 200) { Map<String, Object> tokenData = (Map<String, Object>)JSON.deserializeUntyped(res.getBody()); return (String)tokenData.get('access_token'); } else { throw new Exception('Failed to get token: ' + res.getBody()); } } }
2. gcloud命令行获取临时令牌(仅用于测试)
本地安装Google Cloud SDK后,执行以下命令获取临时令牌,可用于Salesforce测试调用:
gcloud auth print-access-token
注意:该令牌有效期约1小时,仅适合开发测试,不建议生产环境使用。
内容的提问来源于stack exchange,提问作者Dadhich Rami
相关产品推荐
相关产品推荐

