简而言之,我想在Google API上使用服务帐户获取新的访问令牌。我使用了OAuth 2.0和JWT请求。我找到了很多类似的帖子,但没有人回答我的问题。我做的一切都符合Google OAuth 2.0 Server-to-Server request guide,但是当我发送POST请求时,我得到了回报" invalid_grant"。有什么想法吗?这是我的代码:
$jwt_header_array = array( "alg" => "RS256",
"typ" => "JWT");
$jwt_claim_array = array( "iss" => "upload-file@feedking-1355.iam.gserviceaccount.com",
"scope" => "https://www.googleapis.com/auth/drive.file",
"aud" => "https://www.googleapis.com/oauth2/v4/token",
"exp" => time()+3600,
"iat" => time());
$jwt_header = base64_encode(json_encode($jwt_header_array));
$jwt_claim = base64_encode(json_encode($jwt_claim_array));
$key = "-----BEGIN PRIVATE KEY----- privat_key_downloaded_from_google_console -----END PRIVATE KEY-----\n";
$pkeyid = openssl_pkey_get_private($key);
openssl_sign($jwt_header.'.'.$jwt_claim, $jwt_signature, $pkeyid, "sha256");
$jwt_signature = base64_encode($jwt_signature);
$jwt = $jwt_header.'.'.$jwt_claim.'.'.$jwt_signature;
echo $jwt.'<br /><br />';
$url = 'https://www.googleapis.com/oauth2/v4/token';
$query = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion='.$jwt;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
$result = curl_exec($ch);
var_dump($result);
答案 0 :(得分:1)
我找到了一个解决方案,这是非常明显的。为什么不使用Google Utils,Auth和Signer / P12课程?您可以使用composer(google / apiclient)获得整个软件包,除此之外您还需要这个用于进行Google API身份验证(实际上我已经有了这个软件包,愚蠢的我)。我将指导您完成整个过程:
新解决方案:
您将需要Google API套餐和Google服务帐户,如下面的旧解决方案(第1,2,3阶段)所述。从这里只需复制粘贴完全基于API的代码并替换输入数据:
$client_email = 'file-upload-final@feedking-1355.iam.gserviceaccount.com';
$private_key = file_get_contents('p12_final.p12');
$scopes = array('https://www.googleapis.com/auth/drive.file');
$credentials = new Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key
);
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
OLD SOLUTION:
创建Google Service account,因为这对于在未经用户同意的情况下访问Google API至关重要。确保在创建它时,检查&#34;提供新的私钥&#34;和&#34; P12&#34;选项。如果需要,也请检查其他选项。
下载,将P12文件上传到您的服务器/本地,然后存储密码(通常是#34; notasecret&#34;此时......)。
如果您还没有使用composer或GIT安装Google API包。我更喜欢作曲家,因为GIT版本缺少一些库,对我来说Client类有点儿错误(当然可能是我的错)。
您只需使用正确的类来编写和编码JWT标头和playload,并签署证书。请注意P12证书路径以及playload中的相关输入(您可以从Google Developer Console Credetials页面获取所有这些信息,并且您还可以在Google OAuth 2.0 Server-to-Server Application页面上获取有关值的信息)。这是代码:
$header = array("typ" => "JWT",
"alg" => "RS256");
$playload = array( "iss" => "upload-file2@feedking-1355.iam.gserviceaccount.com",
"scope" => "https://www.googleapis.com/auth/drive.file",
"aud" => "https://www.googleapis.com/oauth2/v4/token",
"exp" => time()+3600,
"iat" => time());
$segments = array();
$segments[] = Google_Utils::urlSafeB64Encode(json_encode($header));
$segments[] = Google_Utils::urlSafeB64Encode(json_encode($playload));
$signing_input = implode(".", $segments);
$signer = new Google_Signer_P12(file_get_contents('p12.p12', true), 'notasecret');
$signature = $signer->sign($signing_input);
$segments[] = Google_Utils::urlSafeB64Encode($signature);
$jwt = implode(".", $segments);
$url = 'https://www.googleapis.com/oauth2/v4/token';
$query = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion='.$jwt;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
$result = curl_exec($ch);
string(141)&#34; {&#34; access_token&#34;:&#34; ya29.Ci8QAzKz-U83RiaylDKgSDgH9XEVQrdBAQ5EBxMFUncN7WLfeGan0BCMJRdFJykC-g&#34;,&#34; token_type&#34;:&#34; Bearer& #34;,&#34; expires_in&#34;:3600}&#34;
希望你喜欢它并且会赞成,因为我用这个认证故事搞砸了2天。在某些情况下,Google API可以发挥魔力,因此在inmho中学习它是必不可少的。
答案 1 :(得分:1)
您的代码中只有一个小问题,它会完美运行……原生 php base64_encode()
它与 API 预期的 base64_url_encode()
略有不同
代码如下:
function base64_url_encode(string $input) : string
{
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}
一切都会好起来的。
我知道已经有很多年了(从问题开始)并且 Google 创建了可以通过 Composer
轻松下载和安装的库,但是……
就我而言,我需要在过去 7 天内从 GA 获得访问。使用 Google 的原始库,我可以做到。但它有 66.8 MB 的文件,只是为了解决这个小问题。
我知道也有很多有用的库,但我不需要它们。我只需要在过去 7 天内从 GA 访问。这就是我可以用原生 PHP 和 OpenSSL 函数做的事情……大约 1 kB 的代码。