PHP Google API OAuth2 JWT请求新访问令牌时显示“无效授权”

PHP Google API OAuth2 JWT请求新访问令牌时显示“无效授权”,php,oauth-2.0,jwt,google-api-php-client,google-oauth,Php,Oauth 2.0,Jwt,Google Api Php Client,Google Oauth,简言之,我想通过谷歌API上的服务帐户获得一个新的acces令牌。我使用了OAuth2.0和JWT请求。我发现了许多类似的帖子,但没有一个能回答我的问题。我做的一切都符合要求,但当我发送POST请求时,我得到了无效的授权。你知道为什么吗?这是我的密码: $jwt\u头\u数组=数组alg=>RS256, 典型=>JWT; $jwt\u索赔\u数组=数组iss=>上传-file@feedking-1355.iam.gserviceaccount.com, 范围=>https://www.googl

简言之,我想通过谷歌API上的服务帐户获得一个新的acces令牌。我使用了OAuth2.0和JWT请求。我发现了许多类似的帖子,但没有一个能回答我的问题。我做的一切都符合要求,但当我发送POST请求时,我得到了无效的授权。你知道为什么吗?这是我的密码:

$jwt\u头\u数组=数组alg=>RS256, 典型=>JWT; $jwt\u索赔\u数组=数组iss=>上传-file@feedking-1355.iam.gserviceaccount.com, 范围=>https://www.googleapis.com/auth/drive.file, 澳元=>https://www.googleapis.com/oauth2/v4/token, exp=>time+3600, iat=>时间; $jwt_header=base64_encodejson_encode$jwt_header_数组; $jwt_claim=base64_encodejson_encode$jwt_claim_数组; $key=---开始私钥---从谷歌控制台下载私钥---结束私钥---\n; $pkeyid=openssl\u pkey\u get\u private$key; openssl_签名$jwt_头。'.$jwt_声明,$jwt_签名,$pkeyid,sha256; $jwt_签名=base64_编码$jwt_签名; $jwt=$jwt_标题。'.$jwt_索赔。'.$jwt_签名; echo$jwt。; $url='1https://www.googleapis.com/oauth2/v4/token'; $query='grant_type=urn%3AETF%3Aparams%3OAuth%3AGANT type%3Ajwt承载和断言='。$jwt; $ch=curl\u init; curl_setopt$ch,CURLOPT_URL,$URL; curl_setopt$ch,CURLOPT_HTTPHEADER,数组'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\u exec$ch; var_dump$结果;
我找到了一个解决办法,这是显而易见的。为什么不使用googleutils、Auth和Signer/P12类?您可以使用composer google/apiclient获得整个软件包,此外,您还需要这个软件包来进行google API身份验证。事实上,我已经有了这个软件包,dumb me。我将指导您完成整个过程:

新解决方案:

您将需要Google API包和Google服务帐户,如第1、2、3阶段下面的旧解决方案中所述。从这里复制粘贴完全基于API的代码并替换输入数据:

$client_email='文件上传-final@feedking-1355.iam.gserviceaccount.com'; $private_key=file_get_contents'p12_final.p12'; $scopes=array'https://www.googleapis.com/auth/drive.file'; $credentials=新的谷歌认证断言 $client_电子邮件, $scopes, $private_key ; $client=新的Google_客户端; $client->setAssertionCredentials$credentials; 如果$client->getAuth->isAccessToken过期{ $client->getAuth->refreshTokenWithAssertion; } 旧的解决方案:

创建一个,因为这对于在没有进一步用户同意的情况下访问Google API是至关重要的。确保在创建它时,选中“提供新私钥”和“P12选项”。如果需要,还可以检查其他选项

下载P12文件,将其上传到您的服务器/本地,并将密码存储在此处,这通常不是密码

如果您还没有使用composer或GIT安装GoogleAPI包。我更喜欢composer,因为GIT版本缺少一些库,对我来说,客户端类有点缺陷,这当然可能是我的错

您只需要使用正确的类来生成和编码JWT头和playload,并签署证书。注意P12证书路径,对于playload中的相应输入,您可以从页面获取所有证书路径,还可以获取关于页面上值的信息。代码如下:

$header=arraytyp=>JWT, alg=>RS256; $playload=array-iss=>upload-file2@feedking-1355.iam.gserviceaccount.com, 范围=>https://www.googleapis.com/auth/drive.file, 澳元=>https://www.googleapis.com/oauth2/v4/token, exp=>time+3600, iat=>时间; $segments=数组; $segments[]=Google_Utils::urlSafeB64Encodejson_encode$header; $segments[]=Google_Utils::urlSafeB64Encodejson_encode$playload; $signing_input=内爆,$segments; $signer=新的Google\u signer\u p12文件\u获取内容'p12.p12',true',notasecret'; $signature=$signer->sign$signing\u输入; $segments[]=Google_Utils::urlsafeb64编码$signature; $jwt=内爆,$segments; 使用cURL或任何您想要获取访问令牌的内容发送请求: $url='1https://www.googleapis.com/oauth2/v4/token'; $query='grant_type=urn%3AETF%3Aparams%3OAuth%3AGANT type%3Ajwt承载和断言='。$jwt; $ch=curl\u init; curl_setopt$ch,CURLOPT_URL,$URL; curl_setopt$ch,CURLOPT_HTTPHEADER,数组'Content-Type:application/x-www-form-urlencoded'; curl_setopt$ch,CURLOPT_返回 转移,真实; curl_setopt$ch,CURLOPT_FOLLOWLOCATION,true; curl_setopt$ch,CURLOPT_POST,1; curl_setopt$ch,CURLOPT_POSTFIELDS$query; $result=curl\u exec$ch; 最后,var_dump$结果输出应该类似: string141{access_token:ya29.Ci8QAzKz-U83RiaylDKgSDgH9XEVQrdBAQ5EBxMFUncN7WLfeGan0BCMJRdFJykC-g,token_type:Bearer,expires_in:3600}


希望你喜欢它,并将投票,因为我搞砸了这2天的认证故事。谷歌API在某些情况下可以发挥神奇的作用,因此在MHO中学习它是一件必不可少的事情。

我找到了一个解决方案,这是显而易见的。为什么不使用googleutils、Auth和Signer/P12类?您可以使用composer google/apiclient获得整个软件包,此外,您还需要这个软件包来进行google API身份验证。事实上,我已经有了这个软件包,dumb me。我将指导您完成整个过程:

新解决方案:

您将需要Google API包和Google服务帐户,如第1、2、3阶段下面的旧解决方案中所述。从这里复制粘贴完全基于API的代码并替换输入数据:

$client_email='文件上传-final@feedking-1355.iam.gserviceaccount.com'; $private_key=file_get_contents'p12_final.p12'; $scopes=array'https://www.googleapis.com/auth/drive.file'; $credentials=新的谷歌认证断言 $client_电子邮件, $scopes, $private_key ; $client=新的Google_客户端; $client->setAssertionCredentials$credentials; 如果$client->getAuth->isAccessToken过期{ $client->getAuth->refreshTokenWithAssertion; } 旧的解决方案:

创建一个,因为这对于在没有进一步用户同意的情况下访问Google API是至关重要的。确保在创建它时,选中“提供新私钥”和“P12选项”。如果需要,还可以检查其他选项

下载P12文件,将其上传到您的服务器/本地,并将密码存储在此处,这通常不是密码

如果您还没有使用composer或GIT安装GoogleAPI包。我更喜欢composer,因为GIT版本缺少一些库,对我来说,客户端类有点缺陷,这当然可能是我的错

您只需要使用正确的类来生成和编码JWT头和playload,并签署证书。注意P12证书路径,对于playload中的相应输入,您可以从页面获取所有证书路径,还可以获取关于页面上值的信息。代码如下:

$header=arraytyp=>JWT, alg=>RS256; $playload=array-iss=>upload-file2@feedking-1355.iam.gserviceaccount.com, 范围=>https://www.googleapis.com/auth/drive.file, 澳元=>https://www.googleapis.com/oauth2/v4/token, exp=>time+3600, iat=>时间; $segments=数组; $segments[]=Google_Utils::urlSafeB64Encodejson_encode$header; $segments[]=Google_Utils::urlSafeB64Encodejson_encode$playload; $signing_input=内爆,$segments; $signer=新的Google\u signer\u p12文件\u获取内容'p12.p12',true',notasecret'; $signature=$signer->sign$signing\u输入; $segments[]=Google_Utils::urlsafeb64编码$signature; $jwt=内爆,$segments; 使用cURL或任何您想要获取访问令牌的内容发送请求: $url='1https://www.googleapis.com/oauth2/v4/token'; $query='grant_type=urn%3AETF%3Aparams%3OAuth%3AGANT type%3Ajwt承载和断言='。$jwt; $ch=curl\u init; curl_setopt$ch,CURLOPT_URL,$URL; curl_setopt$ch,CURLOPT_HTTPHEADER,数组'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\u exec$ch; 最后,var_dump$结果输出应该类似: string141{access_token:ya29.Ci8QAzKz-U83RiaylDKgSDgH9XEVQrdBAQ5EBxMFUncN7WLfeGan0BCMJRdFJykC-g,token_type:Bearer,expires_in:3600}


希望你喜欢它,并将投票,因为我搞砸了这2天的认证故事。Google API在某些情况下可以发挥神奇的作用,因此在MHO中学习这是一件必不可少的事情。

您的代码中只有一个小问题,它将完美工作……原生php base64_编码它与API期望的base64_url_编码略有不同

代码如下所示:

函数base64\u url\u encodestring$input:string { 返回str_replace'=',strtrrbase64_encode$input,'+/','-'; } 一切都会好起来的

我知道这是多年来从问题和谷歌创建的图书馆,可以很容易地下载和安装作曲家,但… 在我的情况下,我需要在过去7天内获得来自GA的访问。有了来自谷歌的原始库,我可以做到这一点。但是它有66.8MB的文件,只是为了这个小问题

我知道还有很多有用的库,但我不需要它们。我需要在过去7天内从GA访问。这就是我能做的
使用本机PHP和OpenSSL函数…大约1KB的代码。

您的代码中只有一个小问题,它将工作正常…本机PHP base64\u编码它与API期望的base64\u url\u编码略有不同

代码如下所示:

函数base64\u url\u encodestring$input:string { 返回str_replace'=',strtrrbase64_encode$input,'+/','-'; } 一切都会好起来的

我知道这是多年来从问题和谷歌创建的图书馆,可以很容易地下载和安装作曲家,但… 在我的情况下,我需要在过去7天内获得来自GA的访问。有了来自谷歌的原始库,我可以做到这一点。但是它有66.8MB的文件,只是为了这个小问题


我知道还有很多有用的库,但我不需要它们。我需要在过去7天内访问GA。这就是我可以使用本机PHP和OpenSSL函数做的…大约1KB的代码。

从技术上讲,你需要对JWT元素进行base64url编码,而不是只对它们进行base64编码。这些编码很好,因为我得到了正确的JWT头,并声称与谷歌的示例一样,使用来自该示例的相同输入。唯一的问题是签名,我无法验证,因为密钥与示例中使用的密钥不同。从技术上讲,您需要对JWT元素进行base64url编码,而不仅仅是base64编码。这些编码很好,因为我得到了正确的JWT头并声明,正如Google示例中所述,使用来自该示例的相同输入。唯一的问题是签名,我无法验证,因为密钥与示例中使用的密钥不同。