Google OAuth2 中签名中的 JWT“invalid_grant”

问题描述 投票:0回答:5

我正在编写一些代码来尝试从 Google 获取令牌以在 OAuth2 中使用。这是针对服务帐户的,因此说明如下:

https://developers.google.com/identity/protocols/OAuth2ServiceAccount

当我将 JWT 发布到 Google 时,我不断收到此错误:

{“error”:“invalid_grant”,“error_description”:“无效的 JWT 签名。” }

这是代码:

try{        
    var nowInSeconds : Number = (Date.now() / 1000);
    nowInSeconds = Math.round(nowInSeconds);
    var fiftyNineMinutesFromNowInSeconds : Number = nowInSeconds + (59 * 60);
    
    
    var claimSet : Object = {};
    claimSet.iss   = "{{RemovedForPrivacy}}";        
    claimSet.scope = "https://www.googleapis.com/auth/plus.business.manage";
    claimSet.aud   = "https://www.googleapis.com/oauth2/v4/token";
    claimSet.iat   = nowInSeconds; 
    claimSet.exp   = fiftyNineMinutesFromNowInSeconds;
    
    var header : Object = {};
    header.alg = "RS256";
    header.typ = "JWT";
    
    /* Stringify These */
    var claimSetString = JSON.stringify(claimSet);
    var headerString = JSON.stringify(header);
    
    /* Base64 Encode These */
    var claimSetBaseSixtyFour = StringUtils.encodeBase64(claimSetString);
    var headerBaseSixtyFour = StringUtils.encodeBase64(headerString);
    
    var privateKey = "{{RemovedForPrivacy}}";
    
    /* Create the signature */
    var signature : Signature = Signature();
    signature =  signature.sign(headerBaseSixtyFour + "." + claimSetBaseSixtyFour, privateKey , "SHA256withRSA");
    
    /* Concatenate the whole JWT */
    var JWT = headerBaseSixtyFour + "." + claimSetBaseSixtyFour + "." + signature;
    
    /* Set Grant Type */
    var grantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"
    
    /* Create and encode the body of the token post request */
    var assertions : String = "grant_type=" + dw.crypto.Encoding.toURI(grantType) + "&assertion=" + dw.crypto.Encoding.toURI(JWT);
    
    /* Connect to Google And Ask for Token */
    /* TODO Upload Certs? */
    var httpClient : HTTPClient = new HTTPClient();
    httpClient.setRequestHeader("content-type", "application/x-www-form-urlencoded; charset=utf-8");
    httpClient.timeout = 30000;
    httpClient.open('POST', "https://www.googleapis.com/oauth2/v4/token");
    httpClient.send(assertions);
  
    if (httpClient.statusCode == 200) {
       //nothing
    } else {
       pdict.errorMessage = httpClient.errorText;
    }  
    
}
catch(e){
    Logger.error("The error with the OAuth Token Generator is --> " + e);
}

有人知道 JWT 失败的原因吗?

oauth-2.0 jwt
5个回答
12
投票

问题可能与您的

StringUtils.encodeBase64()
方法可能执行标准的 base64 编码有关。

但是,根据 JWT 规范,需要使用的不是标准的 Base64 编码,而是 URL 和文件名安全的 Base64 编码,并且省略了

=
填充字符。

如果您没有方便的用于base64URL编码的实用方法,您可以通过

进行验证
  • 将所有
    +
    替换为
    -
  • 将所有
    /
    替换为
    _
  • 删除所有
    =

在你的base64编码的字符串中。

另外,你的签名也是base64编码的吗?它需要遵循与上述相同的规则。


3
投票

我以前也遇到过同样的问题,这就是问题所在:

  • 应用名称错误(项目ID)
  • 错误的服务帐户 ID(电子邮件)

1
投票

此错误的另一个原因可能是“您的服务帐户未激活”,通过 Cloud SDK 安装 gsutil,您应该使用服务帐户凭据进行身份验证。

1- 使用现有服务帐户或创建新帐户,然后下载关联的私钥。

2- 使用 gcloud auth activate-service-account 通过服务帐户进行身份验证:

gcloud auth activate-service-account --key-file [KEY_FILE]

其中 [KEY_FILE] 是包含您的服务帐户凭据的文件的名称。

更多详情链接:激活服务帐户


1
投票

如果开发人员错误地复制、编辑和使用服务帐户密钥文件以用于该文件最初的用途之外的目的,也可能会发生这种情况。例如:

  1. 开发人员 A 创建 SA 1
  2. 开发人员 A 使用
    gcloud iam service-accounts keys create ...
    为 SA 1 创建秘密文件,对其进行加密,并将其签入源代码管理
  3. 开发者 B 创建 SA 2
  4. 开发人员 B(错误地)解密并复制步骤 2 中的秘密文件,使用 SA 2 中的数据修改其某些字段,然后尝试在应用程序中使用它

这种情况下的解决方案显然是开发人员 B 删除复制/编辑的文件,并使用 gcloud 创建一个新的秘密文件,就像开发人员 A 在步骤 2 中所做的那样。


0
投票

我在使用服务帐户时也发生了同样的错误。我不知道出了什么问题,所以第二天我又回来了,结果成功了。所以也许 Google Cloud 每隔一段时间就需要一些时间来传播。

© www.soinside.com 2019 - 2024. All rights reserved.