Google 来自 Salesforce 的 JWT 签名无效

Google JWT Invalid Signature from Salesforce

我正在尝试通过从 Salesforce.com 到 Google 的 DFP 的服务帐户进行身份验证。我在之前的 user/credential 对下进行了集成,但需要更新为新用户。

我在 Google 开发人员控制台中创建了 project/user/key 对,并将新服务帐户添加到 DFP 中的网络。然后我将 "iss" 值更改为新用户的电子邮件,并将私钥更改为密钥对中的新私钥。

我现在收到 'Invalid Signature' 错误。

在 SFDC 中,我使用 Crypto.sign 方法和 RSA-SHA256。

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_crypto.htm#apex_System_Crypto_sign

我已验证密钥格式为 PKCS#8,并根据文档删除了 header 和换行符(我什至解码了 ASN.1 格式并检查了节点的一致性) .

我是否错过了连接用户和正确凭据的步骤?有没有办法让我验证我在本地生成的签名以查看我哪里出错了?我看到的唯一区别是旧私钥比当前私钥短。

下面是我用来生成 JWT 的代码(同样,此代码使用不同的用户名和凭证密钥也能正常运行)。

JWTHeader head = new JWTHeader();
head.alg = 'RS256';
head.typ = 'JWT';

JWTClaimSet claim = new JWTClaimSet();
claim.iss = '<username>@*.iam.gserviceaccount.com';
claim.scope = 'https://www.googleapis.com/auth/dfp';
claim.aud = 'https://accounts.google.com/o/oauth2/token';
claim.iat = DateTime.now().getTime() / 1000;
claim.exp = claim.iat + 3600;

System.debug(JSON.serialize(head));
System.debug(JSON.serialize(claim));

String key = '<privatekey>’;
String base = EncodingUtil.urlEncode(EncodingUtil.base64Encode(Blob.valueOf(JSON.serialize(head))), 'UTF-8') + '.' + EncodingUtil.urlEncode(EncodingUtil.base64Encode(Blob.valueOf(JSON.serialize(claim))), 'UTF-8');
String sig = EncodingUtil.urlEncode(EncodingUtil.base64Encode(Crypto.sign('RSA-SHA256', Blob.valueOf(base), EncodingUtil.base64Decode(key))), 'UTF-8');
String body = base + '.' + sig;
System.debug(body);

Http http = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('https://accounts.google.com/o/oauth2/token');
req.setBody('grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=' + body);
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
req.setMethod('POST');
HttpResponse resp = http.send(req);

几天后,我找到了另一个解决问题的方法。问题是 base64urlsafe 编码。这种编码不是在 SFDC 中本地完成的,并且规定从 base64 字符串中删除尾随填充字符。幸运的是,我的原始用户名在声明集中没有使用填充字符编码。使用新用户名时,存在填充字符,必须在签名前将其删除。

这一切都归结为几个字符。