2012-06-14 3 views
1

저장소 API에 대한 API 요청 (GET 버킷)을 만들고 있는데 필요한 매개 변수 중 하나가 '인증'헤더입니다.서비스 계정을 사용하여 Google Cloud Storage REST API에 대한 OAuth2 액세스 토큰을 요청할 때 invalid_grant 오류가 발생했습니다.

서비스 계정을 사용하여 API에 액세스하고 있습니다.

https://developers.google.com/accounts/docs/OAuth2ServiceAccount 문서를 따라 "Authorization"헤더에 대한 액세스 토큰을 얻었으므로 승인 된 요청을 REST API에 보낼 수있었습니다. 문제는 항상 "invalid_grant"오류가 발생하는 것입니다.

사용이 코드를 확인하려면 : "invalid_grant"오류가 발생합니다이 코드에서 뭔가 잘못

<?php 
error_reporting(E_ERROR); 

const CLIENT_ID = 'XXXXXXXXXXXX.apps.googleusercontent.com'; 
const SERVICE_ACCOUNT = '[email protected]'; 
const KEY_FILE = 'XXX.p12'; 

function get_oauth_access_token() 
{ 
    $header[alg] = 'RS256'; 
    $header[typ] = 'JWT'; 

    $header = urlencode(base64_encode(utf8_encode(json_encode($header)))); 

    $assertion_time = time(); 

    $claim[iss] = CLIENT_ID; //also tried SERVICE_ACCOUNT here, no improvement 
    $claim[scope] = 'https://www.googleapis.com/auth/devstorage.read_only'; 
    $claim[aud] = 'https://accounts.google.com/o/oauth2/token'; 
    $claim[exp] = $assertion_time + 3600; 
    $claim[iat] = $assertion_time; 

    $claim = urlencode(base64_encode(utf8_encode(json_encode($claim)))); 

    $data = $header . '.' . $claim; 

    $p12 = file_get_contents(KEY_FILE); 
    $cert = array(); 
    openssl_pkcs12_read($p12, $cert, 'notasecret'); 
    $priv_key_id = openssl_get_privatekey($cert[pkey]); 

    openssl_sign($data, $signature, $priv_key_id, 'sha256'); 

    $signature = urlencode(base64_encode($signature)); 

    $assertion = $data . '.' . $signature; 

    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, 'https://accounts.google.com/o/oauth2/token'); 
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
    curl_setopt($ch, CURLOPT_POST, true); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, array('grant_type'=>'assertion', 
               'assertion_type'=>'http://oauth.net/grant_type/jwt/1.0/bearer', 
               'assertion'=>$assertion)); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 


    $result = curl_exec($ch); 
    $error = curl_error($ch); 

    curl_close($ch); 
    var_dump($result); 
    var_dump($error); 
} 

get_oauth_access_token(); 

있습니까?

답변

0

다음은 Google Cloud Storage RESTful HTTP 인터페이스에서 서비스 계정을 사용하는 간단한 PHP 프로그램입니다. 이 코드를 서비스 계정으로 테스트했는데 제대로 작동하는 것 같습니다. 추가 질문이 있으면 알려주십시오.

<?php 

require_once 'apiClient.php'; 

// Define constants. 
const CLIENT_ID = 'YOUR_CLIENT_ID_GOES_HERE'; 
const SERVICE_ACCOUNT_NAME = 'YOUR_SERVICE_ACCOUNT_NAME_GOES_HERE'; 
const KEY_FILE = 'key.p12'; 
const BUCKET = 'marc-us'; 

// Obtain OAuth 2.0 access token for service account. 
$client = new apiClient(); 
$key = file_get_contents(KEY_FILE); 
$client->setAssertionCredentials(new apiAssertionCredentials(
    SERVICE_ACCOUNT_NAME, 
    array('https://www.googleapis.com/auth/devstorage.full_control'), 
    $key) 
); 
$client::$auth->refreshTokenWithAssertion(); 
$json = $client->getAccessToken(); 
$accessToken = json_decode($json)->access_token; 

// Add access token to Authorization header of HTTP request. 
$ch = curl_init('http://commondatastorage.googleapis.com/' . BUCKET); 
curl_setopt($ch, CURLOPT_HTTPHEADER, 
      array('Authorization: OAuth ' . $accessToken)); 
$resp = curl_exec($ch); 
curl_close($ch); 

// Display results. 
print '<h2>Response:</h2><pre>' . $resp . '</pre>'; 
?> 
+0

아니, 그것은 내가 여기에 언급 한대로 작동하지 않습니다 당신이 제시 한 코드는 입니다 https://groups.google.com/forum/?fromgroups#!topic/gs-discussion/3y_2XVE2q7U 아마 그냥 해결 방법과 액세스 토큰을 얻기 위해 SDK가 필요 bloat 추가합니다. –

0

내 마지막 반응의 코드는 내게 잘 작동하므로 환경 문제에 직면 해 있다고 생각됩니다. 어쨌든 Google PHP 클라이언트 라이브러리의 소유자와상의 한 후 internal refreshTokenWithAssertion() 메소드를 호출하지 않고 액세스 토큰을 새로 고치는 더 좋은 방법을 제공했습니다.

$req = new apiHttpRequest(YOUR_URL); 
    $val = $client->getIo()->authenticatedRequest($req); 

authenticatedRequest를 호출() (그들이 설정하는 경우 주장의 자격 증명) 액세스 토큰을 새로 고침을 담당 필요 : 그는이 기술을 제안했다. 이 접근 방식을 사용하기 위해 위의 코드를 수정했고 나에게 잘 작동합니다. 기능적인 차이는 없지만 이전 버전과 새 버전이 모두 작동하므로 새 버전이 더 효과적이라고 생각합니다. 내부 호출을 피하고 컬 대신 Google PHP 클라이언트 라이브러리를 사용하여 요청을 실행하고 결과가 훨씬 짧아지고, 더 간단한 코드.

<?php 

require_once 'apiClient.php'; 

// Define constants. 
const SERVICE_ACCOUNT_NAME = 'YOUR_SERVICE_ACCOUNT_NAME'; 
const KEY_FILE = 'key.p12'; 
const BUCKET = 'marc-us'; 

// Obtain service account credentials assertion. 
$client = new apiClient(); 
$key = file_get_contents(KEY_FILE); 
$client->setAssertionCredentials(new apiAssertionCredentials(
    SERVICE_ACCOUNT_NAME, 
    array('https://www.googleapis.com/auth/devstorage.full_control'), 
    $key) 
); 

// Create HTTP request, authorize and execute. 
$req = new apiHttpRequest('http://commondatastorage.googleapis.com/' . BUCKET); 
$resp = $client::getIo()->authenticatedRequest($req); 

// Display results. 
print '<h2>Response:</h2>' . $resp->getResponseBody(); 

?> 
2

문제는 사용중인 서버의 시간 일 수 있습니다.

Google Analytics에 문제가 발생했습니다. 모든 코드는 정확하지만 내 서버 시간은 Google의 시간에 비해 몇 초가 남았습니다. 테스트를 위해 서버의 시간을 몇 분 정도 지연시킬 수 있습니다.

예를 들어 서버 시계를 올바르게 유지하려면 NTP을 사용할 수 있습니다.

0

자바와 같은 오류가 발생했습니다. 내 문제는 exp와 iat가 GMT-5이고 API google Auth가 GMT 인 초 단위의 시간이었습니다. 그런 다음 시간을 GMT 값으로 변경했는데 모두 정상입니다.

관련 문제