尝试连接Google Oauth以访问Google API时出现无效的JWT。

4
我试图通过JWT连接到Google API的OAuth,但是我一直遇到这个错误:
{ "error": "invalid_grant", "error_description": "Invalid JWT: Token must be a short-lived token and in a reasonable timeframe" }
在我的JWT声明中,我将iat设置为当前时间减去1970-01-01的秒数,将exp设置为iat + 3600,所以我不知道为什么仍然会出现这个错误。如果有人知道答案,请告诉我!

1
你正在创建自己的 JWT 声明吗?时间需要是当前时间 NTP https://en.wikipedia.org/wiki/Network_Time_Protocol - Linda Lawton - DaImTo
谢谢您的回复,我将时间设置为UTC,但现在出现了无效签名错误,请问我做错了什么? - andy
$sig = hash_hmac('sha256', utf8_encode($base64encodedHeaderAndPayload), "-----BEGIN PRIVATE KEY-----\n privatekey \n-----END PRIVATE KEY-----\n");$signature = base64url_encode($sig); - andy
请注意,我也尝试过创建自己的JWT令牌,但始终无法使其正常工作。我使用的是Google的客户端库,但一直卡在这个问题上。你使用的是哪种编程语言?也许你可以分析一下客户端库的代码。 - Linda Lawton - DaImTo
5个回答

2

不确定您是否曾经使其工作,但是以下简单步骤对我有用,使用PHP函数openssl_sign():

//helper function
function base64url_encode($data) { 
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); 
}

//Google's Documentation of Creating a JWT: https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests

//{Base64url encoded JSON header}
$jwtHeader = base64url_encode(json_encode(array(
    "alg" => "RS256",
    "typ" => "JWT"
)));
//{Base64url encoded JSON claim set}
$now = time();
$jwtClaim = base64url_encode(json_encode(array(
    "iss" => "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
    "scope" => "https://www.googleapis.com/auth/prediction",
    "aud" => "https://www.googleapis.com/oauth2/v4/token",
    "exp" => $now + 3600,
    "iat" => $now
)));
//The base string for the signature: {Base64url encoded JSON header}.{Base64url encoded JSON claim set}
openssl_sign(
    $jwtHeader.".".$jwtClaim,
    $jwtSig,
    $your_private_key_from_google_api_console,
    "sha256WithRSAEncryption"
);
$jwtSign = base64url_encode($jwtSig);

//{Base64url encoded JSON header}.{Base64url encoded JSON claim set}.{Base64url encoded signature}
$jwtAssertion = $jwtHeader.".".$jwtClaim.".".$jwtSig;

1
抱歉我一直忘记更新这个。这确实是正确的答案!虽然现在我不需要再使用它,因为App Engine现在允许我直接访问Cloud Storage。但仍然感谢你提供正确的答案! :) - andy
嘿@Joseph Shih,我遇到了类似的问题,我的错误是“Invalid JWT Signature.”。你能分享一下你的POST请求吗?我猜我在请求正文中有问题,可能是grant_type的问题。 - Michel
@Michel,无效的JWT签名错误意味着您的签名未能验证您的$jwtHeader和$jwtClaim。您是否使用了正确的ISS(服务帐户的电子邮件地址),并且是否使用了来自API控制台的私钥。另外,请记住您需要对签名进行base-64编码(就像上面的示例一样)。 - Joseph Shih
1
没关系 @JosephShih,我已经解决了。我在这里发布了答案:https://stackoverflow.com/questions/48106432/invalid-signature-google-jwt-api 仍然感谢您的回复 :) - Michel

2

我遇到了同样的问题,通过将我的虚拟机时间与公共ntp服务器同步来解决它:

ntpdate ntp.ubuntu.com

1
如果您看到此错误,您需要为令牌设置正确的过期时间。例如:
var currentTime = new Date().getTime() / 1000; //must be in seconds
var exp = currentTime + 60;

var auth_claimset = {
      iss       :   "...",
      scope     :   "...",
      aud       :   "...",
      exp       :   exp,
      iat       :   currentTime 
};

0

所以我已经修改了以下代码: ' $sig = hash('SHA256', $headerAndPayload, $secret); $signature = base64url_encode($sig); $jwt = $headerAndPayload . "." . $signature; ' 出于某种原因,我一直收到签名无效的消息。$secret是我从服务帐户密钥JSON文件中获取的私钥。你知道哪里出了问题吗? - andy
我刚刚发现在PHP中使用哈希并没有使用秘密密钥,所以我应该仍然使用hash_hmac,并且我没有得到结果 :/ - andy
似乎有签名库可以创建符合规范的JWT。例如:https://github.com/namshi/jose - user2705223

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接