Google API OAuth 2.0身份验证返回"invalid_grant" -可能存在私钥签名格式问题? [英] Google API OAuth 2.0 authentication returning "invalid_grant" - possible private key signature format issue?

查看:521
本文介绍了Google API OAuth 2.0身份验证返回"invalid_grant" -可能存在私钥签名格式问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试连接到需要OAuth 2.0身份验证的Google API.第一步需要我生成一个JSON Web令牌(JWT): https: //developers.google.com/accounts/docs/OAuth2ServiceAccount?hl=ru#creatingjwt ,其格式如下:

I am attempting to connect to Google API which requires OAuth 2.0 authentication. The first step requires me to generate a JSON Web Token (JWT): https://developers.google.com/accounts/docs/OAuth2ServiceAccount?hl=ru#creatingjwt with the following format:

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

我正在按照文档中的所有说明进行操作,但继续收到"invalid_grant"错误.我怀疑这与最后一个(签名)部分有关.根据文档:

I'm following all of the directions as per the documentation, but continue to get an "invalid_grant" error. My suspicion is that this is related to the last (signature) portion. According to the documentation:

计算签名时,必须使用JWT标头中的签名算法.GoogleOAuth 2.0授权服务器支持的唯一签名算法是使用SHA-256哈希算法的RSA.在以下示例中的alg字段中表示为RS256 JWT标头."

"The signing algorithm in the JWT header must be used when computing the signature. The only signing algorithm supported by the Google OAuth 2.0 Authorization Server is RSA using SHA-256 hashing algorithm. This is expressed as RS256 in the alg field in the JWT header."

"使用从Google Developers Console获得的私钥,使用SHA256withRSA(也称为带有SHA-256哈希函数的RSASSA-PKCS1-V1_5-SIGN)对输入的UTF-8表示形式进行签名.输出将是字节数组."

"Sign the UTF-8 representation of the input using SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) with the private key obtained from the Google Developers Console. The output will be a byte array."

签名必须随后经过Base64url编码."

"The signature must then be Base64url encoded."

我直接从Google Dev Console复制了私钥(包括"BEGIN PRIVATE KEY"部分),并对其进行了base64编码.这是我正在使用的代码:

I copied the private key directly from the Google Dev Console (including "BEGIN PRIVATE KEY" part) and base64 encoded it. This is the code I am using:

$time = time();
$url = 'https://accounts.google.com/o/oauth2/token';
$assertion = base64_encode('{"alg":"RS256","typ":"JWT"}').'.';
$assertion .= base64_encode('{
   "iss":"'.$this->configs['client_id'].'",
   "scope":"https://www.googleapis.com/auth/youtube",   
   "aud":"'.$url.'",
   "exp":'.($time+3600).',
   "iat":'.$time.'
  }').'.';
$assertion .= base64_encode('[-----BEGIN PRIVATE KEY-----privateKeyHere-----END PRIVATE KEY-----\n]');
$headers = array(
      'Host: accounts.google.com',
      'Content-Type: application/x-www-form-urlencoded'
);
$fields = array(
   'grant_type' => urlencode('urn:ietf:params:oauth:grant-type:jwt-bearer'),
   'assertion'  => urlencode($assertion)
);

$fields_string = '';
foreach($fields as $key => $value) $fields_string .= '&'.$key.'='.$value;
$fields_string = substr($fields_string, 1);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_HEADER, TRUE );
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1 );
$result = curl_exec($ch);
curl_close($ch);
var_dump($result);

关于为什么返回"invalid_grant"错误的任何想法吗?

Any ideas as to why this is returning the "invalid_grant" error?

推荐答案

因为您这样做,您会收到invalid_grant

You receive invalid_grant because you did

1.

'grant_type' => urlencode('urn:ietf:params:oauth:grant-type:jwt-bearer')

将其更改为公正

'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer'

2.

iss字段不是凭据中的ClientID.这是电子邮件地址.

3.

时间应该是UTC,所以你应该这样做

Time should be in UTC, so you should do

$time = gmmktime();

4.

如@ florent-morselli所述,您需要在签名上签名.没错.

As mentioned @florent-morselli you need to sign the signature. This is true.

5.

检查机器时间.重要的是时间应该同步

Check time of your machine. It's important that time should be synchronized

此后一切都会好起来,Google会给您一个access_token.

After this everything will be ok and Google give you an access_token.

顺便说一句:

  privateKey should be without []\n characters (In my case this is lines of 64 symbols)

  CURLOPT_POST takes only true or false

  http_build_query is better way to build queryString

  'Host: accounts.google.com' in $headers is useless, because you set CURLOPT_URL

这篇关于Google API OAuth 2.0身份验证返回"invalid_grant" -可能存在私钥签名格式问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆